alchemy_cms 2.1.12 → 2.2.rc1

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 (405) hide show
  1. data/.travis.yml +1 -1
  2. data/Gemfile +20 -16
  3. data/README.md +11 -7
  4. data/alchemy_cms.gemspec +31 -29
  5. data/app/assets/javascripts/alchemy/alchemy.base.js +234 -233
  6. data/app/assets/javascripts/alchemy/alchemy.buttons.js +26 -26
  7. data/app/assets/javascripts/alchemy/alchemy.datepicker.js +32 -32
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js +78 -78
  9. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +103 -103
  10. data/app/assets/javascripts/alchemy/alchemy.element_editor_selector.js +84 -84
  11. data/app/assets/javascripts/alchemy/alchemy.elements_window.js +88 -88
  12. data/app/assets/javascripts/alchemy/alchemy.file_progress.js +92 -0
  13. data/app/assets/javascripts/alchemy/alchemy.growler.js +23 -23
  14. data/app/assets/javascripts/alchemy/alchemy.html5.js +23 -0
  15. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js +53 -52
  16. data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +33 -30
  17. data/app/assets/javascripts/alchemy/alchemy.js +2 -0
  18. data/app/assets/javascripts/alchemy/alchemy.js_extensions.js +14 -14
  19. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js.coffee +181 -0
  20. data/app/assets/javascripts/alchemy/alchemy.menubar.js +48 -48
  21. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +39 -39
  22. data/app/assets/javascripts/alchemy/alchemy.preview.js +81 -83
  23. data/app/assets/javascripts/alchemy/alchemy.preview_window.js +86 -86
  24. data/app/assets/javascripts/alchemy/alchemy.routes.js.erb +23 -23
  25. data/app/assets/javascripts/alchemy/alchemy.swf_upload.js +208 -353
  26. data/app/assets/javascripts/alchemy/alchemy.uploader.js +279 -0
  27. data/app/assets/javascripts/alchemy/alchemy.windows.js +268 -268
  28. data/app/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +42 -42
  29. data/app/assets/stylesheets/alchemy/_defaults.scss +89 -89
  30. data/app/assets/stylesheets/alchemy/base.css.scss +790 -804
  31. data/app/assets/stylesheets/alchemy/buttons.css.scss +263 -264
  32. data/app/assets/stylesheets/alchemy/dashboard.css.scss +66 -66
  33. data/app/assets/stylesheets/alchemy/elements.css.scss +575 -564
  34. data/app/assets/stylesheets/alchemy/flash.css.scss +45 -45
  35. data/app/assets/stylesheets/alchemy/frame.css.scss +262 -262
  36. data/app/assets/stylesheets/alchemy/icons.css.scss +86 -86
  37. data/app/assets/stylesheets/alchemy/jquery-ui.alchemy.css.scss +706 -707
  38. data/app/assets/stylesheets/alchemy/jquery.Jcrop.css.scss +46 -27
  39. data/app/assets/stylesheets/alchemy/jquery.sb.css.scss +107 -107
  40. data/app/assets/stylesheets/alchemy/login.css.scss +40 -38
  41. data/app/assets/stylesheets/alchemy/menubar.css.scss +84 -82
  42. data/app/assets/stylesheets/alchemy/modules.css.scss +9 -9
  43. data/app/assets/stylesheets/alchemy/pagination.css.scss +49 -49
  44. data/app/assets/stylesheets/alchemy/print.css +7 -7
  45. data/app/assets/stylesheets/alchemy/sitemap.css.scss +185 -154
  46. data/app/assets/stylesheets/alchemy/standard_set.css +205 -206
  47. data/app/assets/stylesheets/alchemy/tables.css.scss +94 -60
  48. data/app/assets/stylesheets/alchemy/tinymce_content.css.scss +34 -34
  49. data/app/assets/stylesheets/alchemy/tinymce_dialog.css.scss +177 -177
  50. data/app/assets/stylesheets/alchemy/upload.css.scss +68 -45
  51. data/app/assets/stylesheets/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css.scss +222 -221
  52. data/app/controllers/alchemy/admin/attachments_controller.rb +100 -100
  53. data/app/controllers/alchemy/admin/base_controller.rb +116 -116
  54. data/app/controllers/alchemy/admin/clipboard_controller.rb +44 -44
  55. data/app/controllers/alchemy/admin/contents_controller.rb +55 -55
  56. data/app/controllers/alchemy/admin/dashboard_controller.rb +12 -11
  57. data/app/controllers/alchemy/admin/elements_controller.rb +109 -109
  58. data/app/controllers/alchemy/admin/essence_audios_controller.rb +8 -8
  59. data/app/controllers/alchemy/admin/essence_files_controller.rb +20 -20
  60. data/app/controllers/alchemy/admin/essence_flashes_controller.rb +8 -8
  61. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +81 -81
  62. data/app/controllers/alchemy/admin/essence_videos_controller.rb +8 -8
  63. data/app/controllers/alchemy/admin/languages_controller.rb +16 -4
  64. data/app/controllers/alchemy/admin/layoutpages_controller.rb +9 -9
  65. data/app/controllers/alchemy/admin/pages_controller.rb +249 -248
  66. data/app/controllers/alchemy/admin/pictures_controller.rb +105 -105
  67. data/app/controllers/alchemy/admin/resources_controller.rb +111 -166
  68. data/app/controllers/alchemy/admin/trash_controller.rb +18 -18
  69. data/app/controllers/alchemy/admin/users_controller.rb +69 -69
  70. data/app/controllers/alchemy/attachments_controller.rb +27 -27
  71. data/app/controllers/alchemy/base_controller.rb +159 -155
  72. data/app/controllers/alchemy/elements_controller.rb +16 -16
  73. data/app/controllers/alchemy/messages_controller.rb +59 -59
  74. data/app/controllers/alchemy/pages_controller.rb +194 -198
  75. data/app/controllers/alchemy/pictures_controller.rb +57 -57
  76. data/app/controllers/alchemy/user_sessions_controller.rb +70 -70
  77. data/app/helpers/alchemy/admin/attachments_helper.rb +7 -7
  78. data/app/helpers/alchemy/admin/base_helper.rb +425 -425
  79. data/app/helpers/alchemy/admin/contents_helper.rb +72 -72
  80. data/app/helpers/alchemy/admin/elements_helper.rb +108 -107
  81. data/app/helpers/alchemy/admin/essences_helper.rb +108 -108
  82. data/app/helpers/alchemy/admin/pages_helper.rb +42 -42
  83. data/app/helpers/alchemy/admin/pictures_helper.rb +26 -26
  84. data/app/helpers/alchemy/base_helper.rb +90 -90
  85. data/app/helpers/alchemy/elements_helper.rb +167 -168
  86. data/app/helpers/alchemy/essences_helper.rb +133 -133
  87. data/app/helpers/alchemy/pages_helper.rb +515 -526
  88. data/app/helpers/alchemy/pictures_helper.rb +19 -0
  89. data/app/mailers/alchemy/messages.rb +13 -13
  90. data/app/mailers/alchemy/notifications.rb +19 -19
  91. data/app/models/alchemy.rb +3 -3
  92. data/app/models/alchemy/attachment.rb +52 -78
  93. data/app/models/alchemy/cell.rb +48 -48
  94. data/app/models/alchemy/content.rb +196 -196
  95. data/app/models/alchemy/element.rb +500 -490
  96. data/app/models/alchemy/essence_audio.rb +7 -7
  97. data/app/models/alchemy/essence_date.rb +10 -10
  98. data/app/models/alchemy/essence_file.rb +7 -7
  99. data/app/models/alchemy/essence_flash.rb +6 -6
  100. data/app/models/alchemy/essence_html.rb +9 -9
  101. data/app/models/alchemy/essence_picture.rb +17 -17
  102. data/app/models/alchemy/essence_richtext.rb +53 -53
  103. data/app/models/alchemy/essence_text.rb +21 -21
  104. data/app/models/alchemy/essence_video.rb +7 -7
  105. data/app/models/alchemy/folded_page.rb +3 -3
  106. data/app/models/alchemy/language.rb +91 -91
  107. data/app/models/alchemy/language/code.rb +14 -14
  108. data/app/models/alchemy/message.rb +48 -45
  109. data/app/models/alchemy/page.rb +555 -558
  110. data/app/models/alchemy/picture.rb +100 -99
  111. data/app/models/alchemy/user.rb +76 -74
  112. data/app/models/alchemy/user_session.rb +8 -8
  113. data/app/sweepers/alchemy/content_sweeper.rb +15 -15
  114. data/app/sweepers/alchemy/pages_sweeper.rb +50 -50
  115. data/app/sweepers/alchemy/pictures_sweeper.rb +14 -14
  116. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +23 -23
  117. data/app/views/alchemy/admin/attachments/_attachment.html.erb +56 -56
  118. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +15 -15
  119. data/app/views/alchemy/admin/attachments/_files_list.html.erb +16 -16
  120. data/app/views/alchemy/admin/attachments/create.js.erb +2 -2
  121. data/app/views/alchemy/admin/attachments/destroy.js.erb +3 -3
  122. data/app/views/alchemy/admin/attachments/edit.html.erb +10 -10
  123. data/app/views/alchemy/admin/attachments/index.html.erb +14 -14
  124. data/app/views/alchemy/admin/attachments/new.html.erb +9 -9
  125. data/app/views/alchemy/admin/clipboard/index.html.erb +21 -21
  126. data/app/views/alchemy/admin/clipboard/insert.js.erb +5 -5
  127. data/app/views/alchemy/admin/contents/_missing.html.erb +1 -1
  128. data/app/views/alchemy/admin/contents/create.js.erb +33 -33
  129. data/app/views/alchemy/admin/contents/destroy.js.erb +5 -5
  130. data/app/views/alchemy/admin/contents/new.html.erb +13 -13
  131. data/app/views/alchemy/admin/contents/order.js.erb +2 -2
  132. data/app/views/alchemy/admin/dashboard/index.html.erb +96 -92
  133. data/app/views/alchemy/admin/elements/_add_content.html.erb +12 -12
  134. data/app/views/alchemy/admin/elements/_element.html.erb +3 -3
  135. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +28 -28
  136. data/app/views/alchemy/admin/elements/_picture_editor.html.erb +21 -21
  137. data/app/views/alchemy/admin/elements/create.js.erb +32 -32
  138. data/app/views/alchemy/admin/elements/index.html.erb +2 -2
  139. data/app/views/alchemy/admin/elements/new.html.erb +31 -31
  140. data/app/views/alchemy/admin/elements/order.js.erb +3 -3
  141. data/app/views/alchemy/admin/elements/trash.js.erb +13 -13
  142. data/app/views/alchemy/admin/elements/update.js.erb +6 -6
  143. data/app/views/alchemy/admin/essence_files/assign.js.erb +6 -6
  144. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +32 -32
  145. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +1 -1
  146. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +1 -1
  147. data/app/views/alchemy/admin/essence_pictures/update.js.erb +11 -11
  148. data/app/views/alchemy/admin/languages/_form.html.erb +51 -45
  149. data/app/views/alchemy/admin/languages/_language.html.erb +45 -45
  150. data/app/views/alchemy/admin/languages/_table.html.erb +25 -25
  151. data/app/views/alchemy/admin/layoutpages/index.html.erb +35 -35
  152. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +42 -42
  153. data/app/views/alchemy/admin/pages/_external_link.html.erb +1 -1
  154. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +27 -27
  155. data/app/views/alchemy/admin/pages/_page.html.erb +112 -112
  156. data/app/views/alchemy/admin/pages/_sitemap.html.erb +1 -1
  157. data/app/views/alchemy/admin/pages/configure.html.erb +71 -69
  158. data/app/views/alchemy/admin/pages/configure_external.html.erb +38 -38
  159. data/app/views/alchemy/admin/pages/destroy.js.erb +10 -10
  160. data/app/views/alchemy/admin/pages/edit.html.erb +165 -165
  161. data/app/views/alchemy/admin/pages/fold.js.erb +2 -2
  162. data/app/views/alchemy/admin/pages/index.html.erb +66 -66
  163. data/app/views/alchemy/admin/pages/locked.html.erb +1 -1
  164. data/app/views/alchemy/admin/pages/new.html.erb +40 -40
  165. data/app/views/alchemy/admin/pages/sort.js.erb +4 -4
  166. data/app/views/alchemy/admin/pages/unlock.js.erb +6 -6
  167. data/app/views/alchemy/admin/pages/update.js.erb +19 -19
  168. data/app/views/alchemy/admin/partials/_flash.html.erb +2 -2
  169. data/app/views/alchemy/admin/partials/_flash_notices.html.erb +1 -1
  170. data/app/views/alchemy/admin/partials/_flash_upload.html.erb +38 -0
  171. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +15 -15
  172. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +8 -8
  173. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +35 -35
  174. data/app/views/alchemy/admin/partials/_search_form.html.erb +14 -14
  175. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +6 -6
  176. data/app/views/alchemy/admin/partials/_upload_form.html.erb +56 -118
  177. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +11 -11
  178. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +71 -71
  179. data/app/views/alchemy/admin/pictures/_picture.html.erb +32 -32
  180. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +26 -26
  181. data/app/views/alchemy/admin/pictures/_pictures_list.html.erb +6 -6
  182. data/app/views/alchemy/admin/pictures/create.js.erb +7 -7
  183. data/app/views/alchemy/admin/pictures/index.html.erb +67 -67
  184. data/app/views/alchemy/admin/pictures/show_in_window.html.erb +5 -4
  185. data/app/views/alchemy/admin/resources/_form.html.erb +25 -19
  186. data/app/views/alchemy/admin/resources/_resource.html.erb +37 -36
  187. data/app/views/alchemy/admin/resources/_table.html.erb +17 -17
  188. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
  189. data/app/views/alchemy/admin/resources/index.html.erb +14 -14
  190. data/app/views/alchemy/admin/trash/index.html.erb +20 -20
  191. data/app/views/alchemy/admin/users/_table.html.erb +52 -52
  192. data/app/views/alchemy/admin/users/_user.html.erb +35 -36
  193. data/app/views/alchemy/admin/users/index.html.erb +26 -27
  194. data/app/views/alchemy/base/error_notice.html.erb +2 -2
  195. data/app/views/alchemy/base/update.js.erb +1 -1
  196. data/app/views/alchemy/elements/_contactform_view.html.erb +76 -76
  197. data/app/views/alchemy/elements/_download_view.html.erb +1 -1
  198. data/app/views/alchemy/elements/_editor_not_found.html.erb +3 -3
  199. data/app/views/alchemy/elements/_searchresult_view.html.erb +2 -2
  200. data/app/views/alchemy/elements/_sitemap_editor.html.erb +1 -1
  201. data/app/views/alchemy/essences/_essence_audio_view.html.erb +13 -13
  202. data/app/views/alchemy/essences/_essence_date_editor.html.erb +10 -10
  203. data/app/views/alchemy/essences/_essence_file_editor.html.erb +62 -62
  204. data/app/views/alchemy/essences/_essence_file_view.html.erb +8 -8
  205. data/app/views/alchemy/essences/_essence_flash_view.html.erb +19 -19
  206. data/app/views/alchemy/essences/_essence_html_editor.html.erb +6 -6
  207. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +73 -73
  208. data/app/views/alchemy/essences/_essence_picture_view.html.erb +34 -34
  209. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +7 -7
  210. data/app/views/alchemy/essences/_essence_text_editor.html.erb +8 -8
  211. data/app/views/alchemy/navigation/_image_link.html.erb +12 -12
  212. data/app/views/alchemy/navigation/_link.html.erb +13 -13
  213. data/app/views/alchemy/navigation/_renderer.html.erb +17 -17
  214. data/app/views/alchemy/page_layouts/_layout_footer.html.erb +1 -1
  215. data/app/views/alchemy/page_layouts/_layout_header.html.erb +1 -1
  216. data/app/views/alchemy/pages/show.rss.builder +14 -14
  217. data/app/views/alchemy/search/_result.html.erb +7 -7
  218. data/app/views/alchemy/user_sessions/leave.html.erb +9 -9
  219. data/app/views/alchemy/user_sessions/login.html.erb +39 -39
  220. data/app/views/alchemy/user_sessions/logout.html.erb +1 -1
  221. data/app/views/layouts/alchemy/admin.html.erb +81 -81
  222. data/app/views/layouts/alchemy/login.html.erb +36 -36
  223. data/app/views/layouts/alchemy/pages.html.erb +48 -27
  224. data/bin/alchemy +136 -134
  225. data/config/alchemy/config.yml +13 -9
  226. data/config/locales/alchemy.de.yml +24 -30
  227. data/config/locales/alchemy.en.yml +11 -28
  228. data/config/routes.rb +146 -146
  229. data/db/migrate/20100607193638_create_essence_pictures.rb +3 -3
  230. data/db/migrate/20101109150312_alter_pages_visible_column_default.rb +1 -1
  231. data/db/migrate/20101109151812_create_languages.rb +3 -3
  232. data/db/migrate/20110115123343_remove_css_class_default_from_essence_pictures.rb +3 -3
  233. data/db/migrate/20110224105120_change_pages_visible_default.rb +3 -3
  234. data/db/migrate/20110228182659_remove_default_page_layout_from_pages.rb +2 -2
  235. data/db/migrate/20110414163140_remove_display_name_from_elements.rb +3 -3
  236. data/db/migrate/20110511100516_rename_essence_texts_title_to_link_title.rb +2 -2
  237. data/db/migrate/20110529130500_add_cell_id_to_elements.rb +3 -3
  238. data/db/migrate/20110530102804_change_pages_page_layout_column.rb +3 -3
  239. data/db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb +1 -1
  240. data/db/migrate/20111116125112_namespace_alchemy_models.rb +21 -21
  241. data/lib/alchemy/auth_engine.rb +5 -5
  242. data/lib/alchemy/capistrano.rb +64 -64
  243. data/lib/alchemy/config.rb +47 -44
  244. data/lib/alchemy/engine.rb +41 -41
  245. data/lib/alchemy/essence.rb +50 -51
  246. data/lib/alchemy/i18n.rb +48 -48
  247. data/lib/alchemy/modules.rb +30 -30
  248. data/lib/alchemy/mount_point.rb +6 -6
  249. data/lib/alchemy/page_layout.rb +94 -93
  250. data/lib/alchemy/resource.rb +82 -0
  251. data/lib/alchemy/resources_helper.rb +56 -0
  252. data/lib/alchemy/scoped_pagination_url_helper.rb +8 -8
  253. data/lib/alchemy/seeder.rb +88 -88
  254. data/lib/alchemy/tinymce.rb +49 -49
  255. data/lib/alchemy/upgrader.rb +103 -103
  256. data/lib/alchemy/version.rb +1 -1
  257. data/lib/alchemy_cms.rb +26 -27
  258. data/lib/extensions/action_view.rb +1 -1
  259. data/lib/extensions/array.rb +3 -3
  260. data/lib/extensions/hash.rb +3 -3
  261. data/lib/middleware/flash_session_cookie.rb +1 -1
  262. data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +24 -24
  263. data/lib/rails/generators/alchemy/elements/elements_generator.rb +7 -7
  264. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +17 -17
  265. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +6 -6
  266. data/lib/rails/generators/alchemy/plugin/templates/authorization_rules.rb +8 -8
  267. data/lib/rails/generators/alchemy/scaffold/files/pages.html.erb +7 -7
  268. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +36 -36
  269. data/lib/rails/templates/alchemy.rb +1 -1
  270. data/lib/tasks/ferret.rake +2 -2
  271. data/lib/tasks/fleximage.rake +32 -32
  272. data/lib/tasks/install.rake +12 -12
  273. data/lib/tasks/upgrade.rake +4 -4
  274. data/spec/controllers/admin/clipboard_controller_spec.rb +43 -43
  275. data/spec/controllers/admin/contents_controller_spec.rb +22 -22
  276. data/spec/controllers/admin/elements_controller_spec.rb +13 -13
  277. data/spec/controllers/admin/languages_controller_spec.rb +31 -0
  278. data/spec/controllers/admin/pages_controller_spec.rb +10 -41
  279. data/spec/controllers/admin/resources_controller_spec.rb +19 -0
  280. data/spec/controllers/admin/trash_controller_spec.rb +11 -11
  281. data/spec/controllers/base_controller_spec.rb +46 -46
  282. data/spec/controllers/pages_controller_spec.rb +102 -92
  283. data/spec/dummy/app/controllers/admin/events_controller.rb +3 -0
  284. data/spec/dummy/app/controllers/errors_controller.rb +5 -0
  285. data/spec/dummy/app/models/event.rb +3 -0
  286. data/spec/dummy/config.ru +1 -1
  287. data/spec/dummy/config/application.rb +3 -0
  288. data/spec/dummy/config/authorization_rules.rb +7 -0
  289. data/spec/dummy/config/environments/development.rb +8 -1
  290. data/spec/dummy/config/environments/production.rb +1 -1
  291. data/spec/dummy/config/environments/test.rb +5 -2
  292. data/spec/dummy/config/routes.rb +9 -1
  293. data/spec/dummy/db/schema.rb +47 -35
  294. data/spec/dummy/public/404.html +19 -7
  295. data/spec/dummy/public/404.html.bak +26 -0
  296. data/spec/dummy/public/422.html +19 -7
  297. data/spec/dummy/public/500.html +19 -7
  298. data/spec/dummy/script/rails +2 -2
  299. data/spec/factories.rb +76 -76
  300. data/spec/helpers/admin/base_helper_spec.rb +21 -21
  301. data/spec/helpers/admin/contents_helper_spec.rb +14 -14
  302. data/spec/helpers/admin/elements_helper_spec.rb +40 -40
  303. data/spec/helpers/admin/essences_helper_spec.rb +7 -7
  304. data/spec/helpers/elements_helper_spec.rb +154 -154
  305. data/spec/helpers/essences_helper_spec.rb +10 -10
  306. data/spec/helpers/pages_helper_spec.rb +369 -372
  307. data/spec/helpers/pictures_helper_spec.rb +14 -0
  308. data/spec/helpers/url_helpers_spec.rb +29 -34
  309. data/spec/integration/admin/pages_controller_spec.rb +50 -50
  310. data/spec/integration/admin/resources_integration_spec.rb +100 -0
  311. data/spec/integration/navigation_spec.rb +1 -1
  312. data/spec/integration/pages_controller_spec.rb +205 -207
  313. data/spec/integration/security_spec.rb +47 -47
  314. data/spec/javascripts/alchemy/link_overlay_spec.js.coffee +42 -0
  315. data/spec/javascripts/alchemy_integration_spec.coffee +12 -0
  316. data/spec/javascripts/fixtures/select.html +3 -0
  317. data/spec/javascripts/helpers/.gitkeep +0 -0
  318. data/spec/javascripts/helpers/jasmine-jquery-1.3.1.js +289 -0
  319. data/spec/javascripts/helpers/mock-ajax.js +207 -0
  320. data/spec/javascripts/helpers/test_responses/test_responses.js +1 -0
  321. data/spec/javascripts/spec.css +3 -0
  322. data/spec/javascripts/spec.js +2 -0
  323. data/spec/libraries/resource_spec.rb +122 -0
  324. data/spec/libraries/resources_helper_spec.rb +105 -0
  325. data/spec/models/content_spec.rb +67 -67
  326. data/spec/models/element_spec.rb +133 -133
  327. data/spec/models/essence_picture_spec.rb +5 -5
  328. data/spec/models/essence_richtext_spec.rb +4 -4
  329. data/spec/models/language_spec.rb +89 -89
  330. data/spec/models/page_spec.rb +436 -506
  331. data/spec/models/picture_spec.rb +34 -34
  332. data/spec/models/user_spec.rb +2 -2
  333. data/spec/page_layout_spec.rb +24 -20
  334. data/spec/routing_spec.rb +253 -253
  335. data/spec/spec_helper.rb +51 -50
  336. data/spec/support/alchemy/controller_hacks.rb +25 -25
  337. data/spec/support/alchemy/specs_helpers.rb +25 -25
  338. data/spec/support/integration_spec_helper.rb +24 -0
  339. data/vendor/assets/javascripts/jquery_plugins/jquery.html5uploader.js +271 -0
  340. data/vendor/assets/javascripts/jquery_plugins/jquery.in-place-edit.js +86 -85
  341. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +380 -377
  342. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +285 -279
  343. data/vendor/assets/javascripts/swfupload/SWFObject License.txt +3 -3
  344. data/vendor/assets/javascripts/swfupload/swfupload.cookies.js +47 -47
  345. data/vendor/assets/javascripts/swfupload/swfupload.js +612 -612
  346. data/vendor/assets/javascripts/swfupload/swfupload.queue.js +93 -93
  347. data/vendor/assets/javascripts/swfupload/swfupload.speed.js +337 -337
  348. data/vendor/assets/javascripts/swfupload/swfupload.swfobject.js +706 -102
  349. data/vendor/assets/javascripts/tiny_mce/license.txt +6 -6
  350. data/vendor/assets/javascripts/tiny_mce/plugins/fullscreen/fullscreen.htm +97 -97
  351. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/template.htm +386 -376
  352. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pastetext.js +30 -30
  353. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pasteword.js +45 -45
  354. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pastetext.htm +20 -17
  355. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pasteword.htm +12 -12
  356. data/vendor/assets/javascripts/tiny_mce/plugins/table/cell.htm +183 -173
  357. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/cell.css +4 -4
  358. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/row.css +7 -7
  359. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/table.css +3 -3
  360. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/cell.js +282 -280
  361. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/merge_cells.js +15 -15
  362. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/row.js +204 -204
  363. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/table.js +435 -435
  364. data/vendor/assets/javascripts/tiny_mce/plugins/table/merge_cells.htm +24 -22
  365. data/vendor/assets/javascripts/tiny_mce/plugins/table/row.htm +144 -136
  366. data/vendor/assets/javascripts/tiny_mce/plugins/table/table.htm +184 -168
  367. data/vendor/assets/javascripts/tiny_mce/themes/advanced/about.htm +62 -46
  368. data/vendor/assets/javascripts/tiny_mce/themes/advanced/anchor.htm +17 -16
  369. data/vendor/assets/javascripts/tiny_mce/themes/advanced/charmap.htm +56 -47
  370. data/vendor/assets/javascripts/tiny_mce/themes/advanced/color_picker.htm +67 -54
  371. data/vendor/assets/javascripts/tiny_mce/themes/advanced/editor_template.js +852 -1
  372. data/vendor/assets/javascripts/tiny_mce/themes/advanced/image.htm +79 -69
  373. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/about.js +48 -48
  374. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/anchor.js +28 -28
  375. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/charmap.js +317 -317
  376. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/color_picker.js +248 -246
  377. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/image.js +246 -246
  378. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/link.js +146 -146
  379. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/source_editor.js +31 -31
  380. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/de.js +1 -1
  381. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/de_dlg.js +1 -1
  382. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/en.js +1 -1
  383. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/en_dlg.js +1 -1
  384. data/vendor/assets/javascripts/tiny_mce/themes/advanced/link.htm +53 -46
  385. data/vendor/assets/javascripts/tiny_mce/themes/advanced/shortcuts.htm +57 -45
  386. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/content.css +182 -47
  387. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/dialog.css +399 -92
  388. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/ui.css +891 -187
  389. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/content.css +102 -24
  390. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +377 -78
  391. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/ui.css +452 -77
  392. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/content.css +167 -45
  393. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css +399 -92
  394. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui.css +890 -190
  395. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +33 -7
  396. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +15 -4
  397. data/vendor/assets/javascripts/tiny_mce/themes/advanced/source_editor.htm +18 -15
  398. data/vendor/assets/javascripts/tiny_mce/utils/editable_selects.js +46 -46
  399. data/vendor/assets/javascripts/tiny_mce/utils/form_utils.js +124 -124
  400. data/vendor/assets/javascripts/tiny_mce/utils/mctabs.js +112 -112
  401. data/vendor/assets/javascripts/tiny_mce/utils/validate.js +213 -213
  402. metadata +102 -115
  403. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js +0 -216
  404. data/lib/tasks/routes.rake +0 -29
  405. data/spec/integration/admin/resources_spec.rb +0 -19
@@ -1,59 +1,59 @@
1
1
  module Alchemy
2
- class PicturesController < Alchemy::BaseController
3
-
4
- caches_page :show, :thumbnail, :zoom
5
-
6
- filter_access_to :thumbnail
7
-
8
- def show
9
- @picture = Picture.find(params[:id])
10
- @size = params[:size]
11
- @crop = !params[:crop].nil?
12
- @crop_from = normalized_size(params[:crop_from])
13
- @crop_size = params[:crop_size]
14
- @padding = params[:padding]
15
- @upsample = !params[:upsample].nil? ? true : false
16
- @effects = params[:effects]
17
- respond_to do |format|
18
- format.jpg
19
- format.png
20
- format.gif
21
- end
22
- end
23
-
24
- def thumbnail
25
- @picture = Picture.find(params[:id])
26
- case params[:size]
27
- when "small"
28
- @size = "80x60"
29
- when "medium"
30
- @size = "160x120"
31
- when "large"
32
- @size = "240x180"
33
- when nil
34
- @size = "111x93"
35
- else
36
- @size = params[:size]
37
- end
38
- if !params[:crop_size].blank? && !params[:crop_from].blank?
39
- @crop = true
40
- elsif params[:crop] == 'crop'
41
- @default_crop = true
42
- end
43
- end
44
-
45
- def zoom
46
- @picture = Picture.find(params[:id])
47
- end
48
-
49
- private
50
-
51
- def normalized_size(size)
52
- return "" if size.blank?
53
- size.split("x").map do |s|
54
- s.to_i < 0 ? 0 : s.to_i
55
- end.join('x')
56
- end
57
-
58
- end
2
+ class PicturesController < Alchemy::BaseController
3
+
4
+ caches_page :show, :thumbnail, :zoom
5
+
6
+ filter_access_to :thumbnail
7
+
8
+ def show
9
+ @picture = Picture.find(params[:id])
10
+ @size = params[:size]
11
+ @crop = !params[:crop].nil?
12
+ @crop_from = normalized_size(params[:crop_from])
13
+ @crop_size = params[:crop_size]
14
+ @padding = params[:padding]
15
+ @upsample = !params[:upsample].nil? ? true : false
16
+ @effects = params[:effects]
17
+ respond_to do |format|
18
+ format.jpg
19
+ format.png
20
+ format.gif
21
+ end
22
+ end
23
+
24
+ def thumbnail
25
+ @picture = Picture.find(params[:id])
26
+ case params[:size]
27
+ when "small"
28
+ @size = "80x60"
29
+ when "medium"
30
+ @size = "160x120"
31
+ when "large"
32
+ @size = "240x180"
33
+ when nil
34
+ @size = "111x93"
35
+ else
36
+ @size = params[:size]
37
+ end
38
+ if !params[:crop_size].blank? && !params[:crop_from].blank?
39
+ @crop = true
40
+ elsif params[:crop] == 'crop'
41
+ @default_crop = true
42
+ end
43
+ end
44
+
45
+ def zoom
46
+ @picture = Picture.find(params[:id])
47
+ end
48
+
49
+ private
50
+
51
+ def normalized_size(size)
52
+ return "" if size.blank?
53
+ size.split("x").map do |s|
54
+ s.to_i < 0 ? 0 : s.to_i
55
+ end.join('x')
56
+ end
57
+
58
+ end
59
59
  end
@@ -1,83 +1,83 @@
1
1
  module Alchemy
2
- class UserSessionsController < Alchemy::BaseController
2
+ class UserSessionsController < Alchemy::BaseController
3
3
 
4
- before_filter :check_user_count, :only => :login
4
+ before_filter :check_user_count, :only => :login
5
5
 
6
- layout 'alchemy/login'
6
+ layout 'alchemy/login'
7
7
 
8
- helper 'Alchemy::Admin::Base'
8
+ helper 'Alchemy::Admin::Base'
9
9
 
10
- # Signup only works if no user is present in database.
11
- def signup
12
- @user_genders = User.genders_for_select
13
- if request.get?
14
- redirect_to admin_dashboard_path if User.count != 0
15
- @user = User.new({:role => 'admin'})
16
- else
17
- @user = User.new(params[:user])
18
- if @user.save
19
- if params[:send_credentials]
20
- Notifications.admin_user_created(@user).deliver
21
- end
22
- redirect_to admin_dashboard_path
23
- end
24
- end
25
- end
10
+ # Signup only works if no user is present in database.
11
+ def signup
12
+ @user_genders = User.genders_for_select
13
+ if request.get?
14
+ redirect_to admin_dashboard_path if User.count != 0
15
+ @user = User.new({:role => 'admin'})
16
+ else
17
+ @user = User.new(params[:user])
18
+ if @user.save
19
+ if params[:send_credentials]
20
+ Notifications.admin_user_created(@user).deliver
21
+ end
22
+ redirect_to admin_dashboard_path
23
+ end
24
+ end
25
+ end
26
26
 
27
- def login
28
- if current_user
29
- redirect_to admin_dashboard_path, :notice => t('You are already logged in')
30
- else
31
- if request.get?
32
- @user_session = UserSession.new()
33
- @user_roles = User::ROLES.map { |role| [User.human_rolename(role), role]}
34
- @user_genders = User.genders_for_select
35
- flash.now[:info] = params[:message] || t("welcome_please_identify_notice")
36
- else
37
- @user_session = UserSession.new(params[:alchemy_user_session])
38
- store_screen_size
39
- if @user_session.save
40
- if session[:redirect_path].blank?
41
- redirect_to admin_dashboard_path
42
- else
43
- # We have to strip double slashes from beginning of path, because of strange rails/rack bug.
44
- redirect_to session[:redirect_path].gsub(/^\/{2,}/, '/')
45
- end
46
- else
47
- render
48
- end
49
- end
50
- end
51
- end
27
+ def login
28
+ if current_user
29
+ redirect_to admin_dashboard_path, :notice => t('You are already logged in')
30
+ else
31
+ if request.get?
32
+ @user_session = UserSession.new()
33
+ @user_roles = User::ROLES.map { |role| [User.human_rolename(role), role] }
34
+ @user_genders = User.genders_for_select
35
+ flash.now[:info] = params[:message] || t("welcome_please_identify_notice")
36
+ else
37
+ @user_session = UserSession.new(params[:alchemy_user_session])
38
+ store_screen_size
39
+ if @user_session.save
40
+ if session[:redirect_path].blank?
41
+ redirect_to admin_dashboard_path
42
+ else
43
+ # We have to strip double slashes from beginning of path, because of strange rails/rack bug.
44
+ redirect_to session[:redirect_path].gsub(/^\/{2,}/, '/')
45
+ end
46
+ else
47
+ render
48
+ end
49
+ end
50
+ end
51
+ end
52
52
 
53
- def leave
54
- ::I18n.locale = current_user.try(:language)
55
- render :layout => false
56
- end
53
+ def leave
54
+ ::I18n.locale = current_user.language.to_sym
55
+ render :layout => false
56
+ end
57
57
 
58
- def logout
59
- message = params[:message] || t("logged_out")
60
- @user_session = UserSession.find
61
- if @user_session
62
- @user_session.destroy
63
- end
64
- flash[:info] = message
65
- redirect_to root_url
66
- end
58
+ def logout
59
+ message = params[:message] || t("logged_out")
60
+ @user_session = UserSession.find
61
+ if @user_session
62
+ @user_session.destroy
63
+ end
64
+ flash[:info] = message
65
+ redirect_to root_url
66
+ end
67
67
 
68
- private
68
+ private
69
69
 
70
- def check_user_count
71
- if User.count == 0
72
- redirect_to :action => 'signup'
73
- else
74
- return true
75
- end
76
- end
70
+ def check_user_count
71
+ if User.count == 0
72
+ redirect_to :action => 'signup'
73
+ else
74
+ return true
75
+ end
76
+ end
77
77
 
78
- def store_screen_size
79
- session[:screen_size] = params[:user_screensize]
80
- end
78
+ def store_screen_size
79
+ session[:screen_size] = params[:user_screensize]
80
+ end
81
81
 
82
- end
82
+ end
83
83
  end
@@ -1,11 +1,11 @@
1
1
  module Alchemy
2
- module Admin
3
- module AttachmentsHelper
2
+ module Admin
3
+ module AttachmentsHelper
4
4
 
5
- def mime_to_human mime
6
- Alchemy::I18n.t(mime, :scope => :mime_types, :default => t('document'))
7
- end
5
+ def mime_to_human mime
6
+ Alchemy::I18n.t(mime, :scope => :mime_types, :default => t('document'))
7
+ end
8
8
 
9
- end
10
- end
9
+ end
10
+ end
11
11
  end
@@ -1,455 +1,455 @@
1
1
  module Alchemy
2
- module Admin
3
-
4
- # This module contains helper methods for rendering overlay windows, toolbar buttons and confirmation windows.
5
- #
6
- # The most important helpers for module developers are:
7
- #
8
- # * toolbar
9
- # * toolbar_button
10
- # * link_to_overlay_window
11
- # * link_to_confirmation_window
12
- #
13
- module BaseHelper
2
+ module Admin
14
3
 
15
- # This helper renders the link for an overlay window.
16
- #
17
- # We use this for our fancy modal overlay windows in the Alchemy cockpit.
18
- #
19
- # === Options:
20
- #
21
- # :size [String] # String with format of "WidthxHeight". I.E. ("420x280")
22
- # :title [String] # Text for the overlay title bar.
23
- # :overflow [Boolean] # Should the dialog have overlapping content. If not, it shows scrollbars. Good for select boxes. Default false.
24
- # :resizable [Boolean] # Is the dialog window resizable? Default false.
25
- # :modal [Boolean] # Show as modal window. Default true.
26
- #
27
- def link_to_overlay_window(content, url, options={}, html_options={})
28
- default_options = {
29
- :modal => true,
30
- :overflow => false,
31
- :resizable => false
32
- }
33
- options = default_options.merge(options)
34
- link_to_function(
35
- content,
36
- "Alchemy.openWindow(
37
- \'#{url}\',
38
- \'#{options[:title]}\',
39
- \'#{options[:size] ? options[:size].split('x')[0].to_s : 'auto'}\',
40
- \'#{options[:size] ? options[:size].split('x')[1].to_s : 'auto'}\',
41
- #{options[:resizable]},
42
- #{options[:modal]},
43
- #{options[:overflow]}
44
- )",
45
- html_options
46
- )
47
- end
4
+ # This module contains helper methods for rendering overlay windows, toolbar buttons and confirmation windows.
5
+ #
6
+ # The most important helpers for module developers are:
7
+ #
8
+ # * toolbar
9
+ # * toolbar_button
10
+ # * link_to_overlay_window
11
+ # * link_to_confirmation_window
12
+ #
13
+ module BaseHelper
48
14
 
49
- # (internal) Used for rendering the folder link in +Admin::Pages#index+ sitemap.
50
- def sitemapFolderLink(page)
51
- return '' if page.level == 1
52
- if page.folded?(current_user.id)
53
- css_class = 'folded'
54
- title = t('Show childpages')
55
- else
56
- css_class = 'collapsed'
57
- title = t('Hide childpages')
58
- end
59
- link_to(
60
- '',
61
- alchemy.fold_admin_page_path(page),
62
- :remote => true,
63
- :method => :post,
64
- :class => "page_folder #{css_class}",
65
- :title => title,
66
- :id => "fold_button_#{page.id}"
67
- )
68
- end
15
+ # This helper renders the link for an overlay window.
16
+ #
17
+ # We use this for our fancy modal overlay windows in the Alchemy cockpit.
18
+ #
19
+ # === Options:
20
+ #
21
+ # :size [String] # String with format of "WidthxHeight". I.E. ("420x280")
22
+ # :title [String] # Text for the overlay title bar.
23
+ # :overflow [Boolean] # Should the dialog have overlapping content. If not, it shows scrollbars. Good for select boxes. Default false.
24
+ # :resizable [Boolean] # Is the dialog window resizable? Default false.
25
+ # :modal [Boolean] # Show as modal window. Default true.
26
+ #
27
+ def link_to_overlay_window(content, url, options={}, html_options={})
28
+ default_options = {
29
+ :modal => true,
30
+ :overflow => false,
31
+ :resizable => false
32
+ }
33
+ options = default_options.merge(options)
34
+ link_to_function(
35
+ content,
36
+ "Alchemy.openWindow(
37
+ \'#{url}\',
38
+ \'#{options[:title]}\',
39
+ \'#{options[:size] ? options[:size].split('x')[0].to_s : 'auto'}\',
40
+ \'#{options[:size] ? options[:size].split('x')[1].to_s : 'auto'}\',
41
+ #{options[:resizable]},
42
+ #{options[:modal]},
43
+ #{options[:overflow]}
44
+ )",
45
+ html_options
46
+ )
47
+ end
69
48
 
70
- # Used for language selector in Alchemy cockpit sitemap. So the user can select the language branche of the page.
71
- def language_codes_for_select
72
- configuration(:languages).collect{ |language|
73
- language[:language_code]
74
- }
75
- end
49
+ # (internal) Used for rendering the folder link in +Admin::Pages#index+ sitemap.
50
+ def sitemapFolderLink(page)
51
+ return '' if page.level == 1
52
+ if page.folded?(current_user.id)
53
+ css_class = 'folded'
54
+ title = t('Show childpages')
55
+ else
56
+ css_class = 'collapsed'
57
+ title = t('Hide childpages')
58
+ end
59
+ link_to(
60
+ '',
61
+ alchemy.fold_admin_page_path(page),
62
+ :remote => true,
63
+ :method => :post,
64
+ :class => "page_folder #{css_class}",
65
+ :title => title,
66
+ :id => "fold_button_#{page.id}"
67
+ )
68
+ end
76
69
 
77
- # Used for translations selector in Alchemy cockpit user settings.
78
- def translations_for_select
79
- Alchemy::I18n.available_locales.map do |locale|
80
- [t(locale, :scope => :translations), locale]
81
- end
82
- end
70
+ # Used for language selector in Alchemy cockpit sitemap. So the user can select the language branche of the page.
71
+ def language_codes_for_select
72
+ configuration(:languages).collect { |language|
73
+ language[:language_code]
74
+ }
75
+ end
83
76
 
84
- # Used by Alchemy to display a javascript driven filter for lists in the Alchemy cockpit.
85
- def js_filter_field options = {}
86
- default_options = {
87
- :class => "thin_border js_filter_field",
88
- :onkeyup => "Alchemy.ListFilter('#contact_list li')",
89
- :id => "search_field"
90
- }
91
- options = default_options.merge(options)
92
- options[:onkeyup] << ";jQuery('#search_field').val().length >= 1 ? jQuery('.js_filter_field_clear').show() : jQuery('.js_filter_field_clear').hide();"
93
- filter_field = "<div class=\"js_filter_field_box\">"
94
- filter_field << text_field_tag("filter", '', options)
95
- filter_field << content_tag('span', '', :class => 'icon search')
96
- filter_field << link_to_function(
97
- "",
98
- "jQuery('##{options[:id]}').val('');#{options[:onkeyup]}",
99
- :class => "js_filter_field_clear",
100
- :style => "display:none",
101
- :title => t("click_to_show_all")
102
- )
103
- filter_field << "<label for=\"search_field\">" + t("search") + "</label>"
104
- filter_field << "</div>"
105
- filter_field.html_safe
106
- end
77
+ # Used for translations selector in Alchemy cockpit user settings.
78
+ def translations_for_select
79
+ Alchemy::I18n.available_locales.map do |locale|
80
+ [t(locale, :scope => :translations), locale]
81
+ end
82
+ end
107
83
 
108
- # Returns a link that opens a modal confirmation window.
109
- #
110
- # === Parameters:
111
- #
112
- # 1. The content inside the <a> tag
113
- # 2. The message that is displayed in the overlay window
114
- # 3. The url that gets opened after confirmation (Note: This is an Ajax request with a method of DELETE!)
115
- # 4. html options get passed to the link
116
- #
117
- # === Example:
118
- #
119
- # <%= link_to_confirmation_window('delete', 'Do you really want to delete this comment?', '/admin/comments/1') %>
120
- #
121
- def link_to_confirmation_window(link_string = "", message = "", url = "", html_options = {})
122
- title = t("please_confirm")
123
- ok_lable = t("Yes")
124
- cancel_lable = t("No")
125
- link_to_function(
126
- link_string,
127
- "Alchemy.confirmToDeleteWindow('#{url}', '#{title}', '#{message}', '#{ok_lable}', '#{cancel_lable}');",
128
- html_options
129
- )
130
- end
84
+ # Used by Alchemy to display a javascript driven filter for lists in the Alchemy cockpit.
85
+ def js_filter_field options = {}
86
+ default_options = {
87
+ :class => "thin_border js_filter_field",
88
+ :onkeyup => "Alchemy.ListFilter('#contact_list li')",
89
+ :id => "search_field"
90
+ }
91
+ options = default_options.merge(options)
92
+ options[:onkeyup] << ";jQuery('#search_field').val().length >= 1 ? jQuery('.js_filter_field_clear').show() : jQuery('.js_filter_field_clear').hide();"
93
+ filter_field = "<div class=\"js_filter_field_box\">"
94
+ filter_field << text_field_tag("filter", '', options)
95
+ filter_field << content_tag('span', '', :class => 'icon search')
96
+ filter_field << link_to_function(
97
+ "",
98
+ "jQuery('##{options[:id]}').val('');#{options[:onkeyup]}",
99
+ :class => "js_filter_field_clear",
100
+ :style => "display:none",
101
+ :title => t("click_to_show_all")
102
+ )
103
+ filter_field << "<label for=\"search_field\">" + t("search") + "</label>"
104
+ filter_field << "</div>"
105
+ filter_field.html_safe
106
+ end
131
107
 
132
- # Returns an Array build for passing it to the options_for_select helper inside an essence editor partial.
133
- # Usefull for the select_values options from the render_essence_editor helpers.
134
- #
135
- # == Options:
136
- #
137
- # :from_page [String, Page] # Return only elements from this page. You can either pass a Page instance, or a page_layout name
138
- # :elements_with_name [Array, String] # Return only elements with this name(s).
139
- #
140
- def elements_for_essence_editor_select(options={})
141
- defaults = {
142
- :from_page => nil,
143
- :elements_with_name => nil,
144
- :prompt => t('Please choose')
145
- }
146
- options = defaults.merge(options)
147
- if options[:from_page]
148
- page = options[:from_page].is_a?(String) ? Page.find_by_page_layout(options[:from_page]) : options[:from_page]
149
- end
150
- if page
151
- elements = options[:elements_with_name].blank? ? page.elements.find_all_by_public(true) : page.elements.find_all_by_public_and_name(true, options[:elements_with_name])
152
- else
153
- elements = options[:elements_with_name].blank? ? Element.find_all_by_public(true) : Element.find_all_by_public_and_name(true, options[:elements_with_name])
154
- end
155
- select_options = [[options[:prompt], ""]]
156
- elements.each do |e|
157
- select_options << [e.display_name_with_preview_text, e.id.to_s]
158
- end
159
- select_options
160
- end
108
+ # Returns a link that opens a modal confirmation window.
109
+ #
110
+ # === Parameters:
111
+ #
112
+ # 1. The content inside the <a> tag
113
+ # 2. The message that is displayed in the overlay window
114
+ # 3. The url that gets opened after confirmation (Note: This is an Ajax request with a method of DELETE!)
115
+ # 4. html options get passed to the link
116
+ #
117
+ # === Example:
118
+ #
119
+ # <%= link_to_confirmation_window('delete', 'Do you really want to delete this comment?', '/admin/comments/1') %>
120
+ #
121
+ def link_to_confirmation_window(link_string = "", message = "", url = "", html_options = {})
122
+ title = t("please_confirm")
123
+ ok_lable = t("Yes")
124
+ cancel_lable = t("No")
125
+ link_to_function(
126
+ link_string,
127
+ "Alchemy.confirmToDeleteWindow('#{url}', '#{title}', '#{message}', '#{ok_lable}', '#{cancel_lable}');",
128
+ html_options
129
+ )
130
+ end
161
131
 
162
- # Returns all public pages found in the database as an Array suitable or the Rails +select_tag+ helper.
163
- #
164
- # * You can pass a collection of pages so it only returns these pages and does not query the database.
165
- # * Pass a +Page#name+ or +Page#id+ as second parameter to be passed as selected item to the +options_for_select+ helper.
166
- # * The trhird parameter is used as prompt message in the select tag
167
- # * The last parameter is the method that is called on the page object to get the value that is passed with the params of the form.
168
- #
169
- def pages_for_select(pages = nil, selected = nil, prompt = "", page_attribute = :id)
170
- result = [[prompt.blank? ? t('Choose page') : prompt, ""]]
171
- if pages.blank?
172
- pages = Page.find_all_by_language_id_and_public(session[:language_id], true)
173
- end
174
- pages.each do |p|
175
- result << [p.name, p.send(page_attribute).to_s]
176
- end
177
- options_for_select(result, selected.to_s)
178
- end
132
+ # Returns an Array build for passing it to the options_for_select helper inside an essence editor partial.
133
+ # Usefull for the select_values options from the render_essence_editor helpers.
134
+ #
135
+ # == Options:
136
+ #
137
+ # :from_page [String, Page] # Return only elements from this page. You can either pass a Page instance, or a page_layout name
138
+ # :elements_with_name [Array, String] # Return only elements with this name(s).
139
+ #
140
+ def elements_for_essence_editor_select(options={})
141
+ defaults = {
142
+ :from_page => nil,
143
+ :elements_with_name => nil,
144
+ :prompt => t('Please choose')
145
+ }
146
+ options = defaults.merge(options)
147
+ if options[:from_page]
148
+ page = options[:from_page].is_a?(String) ? Page.find_by_page_layout(options[:from_page]) : options[:from_page]
149
+ end
150
+ if page
151
+ elements = options[:elements_with_name].blank? ? page.elements.find_all_by_public(true) : page.elements.find_all_by_public_and_name(true, options[:elements_with_name])
152
+ else
153
+ elements = options[:elements_with_name].blank? ? Element.find_all_by_public(true) : Element.find_all_by_public_and_name(true, options[:elements_with_name])
154
+ end
155
+ select_options = [[options[:prompt], ""]]
156
+ elements.each do |e|
157
+ select_options << [e.display_name_with_preview_text, e.id.to_s]
158
+ end
159
+ select_options
160
+ end
179
161
 
180
- def render_essence_selection_editor(element, content, select_options)
181
- if content.class == String
182
- content = element.contents.find_by_name(content)
183
- else
184
- content = element.contents[content - 1]
185
- end
186
- if content.essence.nil?
187
- return warning('Element', t('content_essence_not_found'))
188
- end
189
- select_options = options_for_select(select_options, content.essence.content)
190
- select_tag(
191
- "contents[content_#{content.id}]",
192
- select_options,
193
- :class => 'alchemy_selectbox'
194
- )
195
- end
162
+ # Returns all public pages found in the database as an Array suitable or the Rails +select_tag+ helper.
163
+ #
164
+ # * You can pass a collection of pages so it only returns these pages and does not query the database.
165
+ # * Pass a +Page#name+ or +Page#id+ as second parameter to be passed as selected item to the +options_for_select+ helper.
166
+ # * The trhird parameter is used as prompt message in the select tag
167
+ # * The last parameter is the method that is called on the page object to get the value that is passed with the params of the form.
168
+ #
169
+ def pages_for_select(pages = nil, selected = nil, prompt = "", page_attribute = :id)
170
+ result = [[prompt.blank? ? t('Choose page') : prompt, ""]]
171
+ if pages.blank?
172
+ pages = Page.find_all_by_language_id_and_public(session[:language_id], true)
173
+ end
174
+ pages.each do |p|
175
+ result << [p.name, p.send(page_attribute).to_s]
176
+ end
177
+ options_for_select(result, selected.to_s)
178
+ end
196
179
 
197
- def admin_main_navigation
198
- entries = ""
199
- alchemy_modules.each do |alchemy_module|
200
- entries << alchemy_main_navigation_entry(alchemy_module)
201
- end
202
- entries.html_safe
203
- end
180
+ def render_essence_selection_editor(element, content, select_options)
181
+ if content.class == String
182
+ content = element.contents.find_by_name(content)
183
+ else
184
+ content = element.contents[content - 1]
185
+ end
186
+ if content.essence.nil?
187
+ return warning('Element', t('content_essence_not_found'))
188
+ end
189
+ select_options = options_for_select(select_options, content.essence.content)
190
+ select_tag(
191
+ "contents[content_#{content.id}]",
192
+ select_options,
193
+ :class => 'alchemy_selectbox'
194
+ )
195
+ end
204
196
 
205
- def alchemy_main_navigation_entry(alchemy_module)
206
- render 'alchemy/admin/partials/main_navigation_entry', :alchemy_module => alchemy_module.stringify_keys, :navigation => alchemy_module['navigation'].stringify_keys
207
- end
197
+ def admin_main_navigation
198
+ entries = ""
199
+ alchemy_modules.each do |alchemy_module|
200
+ entries << alchemy_main_navigation_entry(alchemy_module)
201
+ end
202
+ entries.html_safe
203
+ end
208
204
 
209
- def admin_subnavigation
210
- alchemy_module = module_definition_for(:controller => params[:controller], :action => 'index')
211
- unless alchemy_module.nil?
212
- entries = alchemy_module["navigation"].stringify_keys['sub_navigation']
213
- render_admin_subnavigation(entries) unless entries.nil?
214
- else
215
- ""
216
- end
217
- end
205
+ def alchemy_main_navigation_entry(alchemy_module)
206
+ render 'alchemy/admin/partials/main_navigation_entry', :alchemy_module => alchemy_module.stringify_keys, :navigation => alchemy_module['navigation'].stringify_keys
207
+ end
218
208
 
219
- # Renders the Subnavigation for the admin interface.
220
- def render_admin_subnavigation(entries)
221
- render "alchemy/admin/partials/sub_navigation_tab", :entries => entries
222
- end
209
+ def admin_subnavigation
210
+ alchemy_module = module_definition_for(:controller => params[:controller], :action => 'index')
211
+ unless alchemy_module.nil?
212
+ entries = alchemy_module["navigation"].stringify_keys['sub_navigation']
213
+ render_admin_subnavigation(entries) unless entries.nil?
214
+ else
215
+ ""
216
+ end
217
+ end
223
218
 
224
- # Used for checking the main navi permissions
225
- def navigate_module(navigation)
226
- [navigation["action"].to_sym, navigation["controller"].gsub(/^\//, '').gsub(/\//, '_').to_sym]
227
- end
219
+ # Renders the Subnavigation for the admin interface.
220
+ def render_admin_subnavigation(entries)
221
+ render "alchemy/admin/partials/sub_navigation_tab", :entries => entries
222
+ end
228
223
 
229
- # Returns true if the current controller and action is in a modules navigation definition.
230
- def admin_mainnavi_active?(mainnav)
231
- mainnav.stringify_keys!
232
- subnavi = mainnav["sub_navigation"].map(&:stringify_keys) if mainnav["sub_navigation"]
233
- nested = mainnav["nested"].map(&:stringify_keys) if mainnav["nested"]
234
- if subnavi
235
- (!subnavi.detect{ |subnav| subnav["controller"].gsub(/^\//, '') == params[:controller] && subnav["action"] == params[:action] }.blank?) ||
236
- (nested && !nested.detect{ |n| n["controller"] == params[:controller] && n["action"] == params[:action] }.blank?)
237
- else
238
- mainnav["controller"] == params[:controller] && mainnav["action"] == params["action"]
239
- end
240
- end
224
+ # Used for checking the main navi permissions
225
+ def navigate_module(navigation)
226
+ [navigation["action"].to_sym, navigation["controller"].gsub(/^\//, '').gsub(/\//, '_').to_sym]
227
+ end
241
228
 
242
- def admin_sub_navigation_entry_active?(entry)
243
- params[:controller] == entry["controller"].gsub(/^\//, '') && ( params[:action] == entry["action"] || entry["nested_actions"] && entry["nested_actions"].include?(params[:action]) )
244
- end
229
+ # Returns true if the current controller and action is in a modules navigation definition.
230
+ def admin_mainnavi_active?(mainnav)
231
+ mainnav.stringify_keys!
232
+ subnavi = mainnav["sub_navigation"].map(&:stringify_keys) if mainnav["sub_navigation"]
233
+ nested = mainnav["nested"].map(&:stringify_keys) if mainnav["nested"]
234
+ if subnavi
235
+ (!subnavi.detect { |subnav| subnav["controller"].gsub(/^\//, '') == params[:controller] && subnav["action"] == params[:action] }.blank?) ||
236
+ (nested && !nested.detect { |n| n["controller"] == params[:controller] && n["action"] == params[:action] }.blank?)
237
+ else
238
+ mainnav["controller"] == params[:controller] && mainnav["action"] == params["action"]
239
+ end
240
+ end
245
241
 
246
- # Calls the url_for helper on either an alchemy module engine, or the app alchemy is mounted at.
247
- def url_for_module(alchemy_module)
248
- navigation = alchemy_module['navigation'].stringify_keys
249
- url_options = {
250
- :controller => navigation['controller'],
251
- :action => navigation['action']
252
- }
253
- if alchemy_module['engine_name']
254
- eval(alchemy_module['engine_name']).url_for(url_options)
255
- else
256
- main_app.url_for(url_options)
257
- end
258
- end
242
+ def admin_sub_navigation_entry_active?(entry)
243
+ params[:controller] == entry["controller"].gsub(/^\//, '') && (params[:action] == entry["action"] || entry["nested_actions"] && entry["nested_actions"].include?(params[:action]))
244
+ end
259
245
 
260
- # Calls the url_for helper on either an alchemy module engine, or the app alchemy is mounted at.
261
- def url_for_module_sub_navigation(navigation)
262
- alchemy_module = module_definition_for(navigation)
263
- engine_name = alchemy_module['engine_name'] if alchemy_module
264
- navigation.stringify_keys!
265
- url_options = {
266
- :controller => navigation['controller'],
267
- :action => navigation['action']
268
- }
269
- if engine_name
270
- eval(engine_name).url_for(url_options)
271
- else
272
- main_app.url_for(url_options)
273
- end
274
- end
246
+ # Calls the url_for helper on either an alchemy module engine, or the app alchemy is mounted at.
247
+ def url_for_module(alchemy_module)
248
+ navigation = alchemy_module['navigation'].stringify_keys
249
+ url_options = {
250
+ :controller => navigation['controller'],
251
+ :action => navigation['action']
252
+ }
253
+ if alchemy_module['engine_name']
254
+ eval(alchemy_module['engine_name']).url_for(url_options)
255
+ else
256
+ main_app.url_for(url_options)
257
+ end
258
+ end
275
259
 
276
- def main_navigation_css_classes(navigation)
277
- ['main_navi_entry', admin_mainnavi_active?(navigation) ? 'active' : nil].compact.join(" ")
278
- end
260
+ # Calls the url_for helper on either an alchemy module engine, or the app alchemy is mounted at.
261
+ def url_for_module_sub_navigation(navigation)
262
+ alchemy_module = module_definition_for(navigation)
263
+ engine_name = alchemy_module['engine_name'] if alchemy_module
264
+ navigation.stringify_keys!
265
+ url_options = {
266
+ :controller => navigation['controller'],
267
+ :action => navigation['action']
268
+ }
269
+ if engine_name
270
+ eval(engine_name).url_for(url_options)
271
+ else
272
+ main_app.url_for(url_options)
273
+ end
274
+ end
279
275
 
280
- # (internal) Renders translated Module Names for html title element.
281
- def render_alchemy_title
282
- if content_for?(:title)
283
- title = content_for(:title)
284
- else
285
- title = t(controller_name, :scope => :modules)
286
- end
287
- "Alchemy CMS - #{title}"
288
- end
276
+ def main_navigation_css_classes(navigation)
277
+ ['main_navi_entry', admin_mainnavi_active?(navigation) ? 'active' : nil].compact.join(" ")
278
+ end
289
279
 
290
- # (internal) Returns max image count as integer or nil. Used for the picture editor in element editor views.
291
- def max_image_count
292
- return nil if !@options
293
- if @options[:maximum_amount_of_images].blank?
294
- image_count = @options[:max_images]
295
- else
296
- image_count = @options[:maximum_amount_of_images]
297
- end
298
- if image_count.blank?
299
- nil
300
- else
301
- image_count.to_i
302
- end
303
- end
280
+ # (internal) Renders translated Module Names for html title element.
281
+ def render_alchemy_title
282
+ if content_for?(:title)
283
+ title = content_for(:title)
284
+ else
285
+ title = t(controller_name, :scope => :libraries)
286
+ end
287
+ "Alchemy CMS - #{title}"
288
+ end
304
289
 
305
- # (internal) Renders a select tag for all items in the clipboard
306
- def clipboard_select_tag(items, html_options = {})
307
- options = [[t('Please choose'), ""]]
308
- items.each do |item|
309
- options << [item.class.to_s == 'Alchemy::Element' ? item.display_name_with_preview_text : item.name, item.id]
310
- end
311
- select_tag(
312
- 'paste_from_clipboard',
313
- !@page.new_record? && @page.can_have_cells? ? grouped_elements_for_select(items, :id) : options_for_select(options),
314
- {
315
- :class => [html_options[:class], 'alchemy_selectbox'].join(' '),
316
- :style => html_options[:style]
317
- }
318
- )
319
- end
290
+ # (internal) Returns max image count as integer or nil. Used for the picture editor in element editor views.
291
+ def max_image_count
292
+ return nil if !@options
293
+ if @options[:maximum_amount_of_images].blank?
294
+ image_count = @options[:max_images]
295
+ else
296
+ image_count = @options[:maximum_amount_of_images]
297
+ end
298
+ if image_count.blank?
299
+ nil
300
+ else
301
+ image_count.to_i
302
+ end
303
+ end
320
304
 
321
- # Renders a toolbar button for the Alchemy toolbar
322
- #
323
- # == Options:
324
- #
325
- # :icon [String] # Icon class. See base.css.sccs for available icons, or make your own.
326
- # :label [String] # Text for button label.
327
- # :url [String] # Url for link.
328
- # :title [String] # Text for title tag.
329
- # :overlay [Boolean] # Pass true to open the link in a modal overlay window.
330
- # :overlay_options [Hash] # Overlay options. See link_to_overlay_window helper.
331
- # :if_permitted_to [Array] # Check permission for button. [:action, :controller]. Exactly how you defined the permission in your +authorization_rules.rb+. Defaults to controller and action from button url.
332
- # :skip_permission_check [Boolean] # Skip the permission check. Default false. NOT RECOMMENDED!
333
- # :loading_indicator [Boolean] # Shows the please wait overlay while loading. Default false.
334
- #
335
- def toolbar_button(options = {})
336
- options.symbolize_keys!
337
- defaults = {
338
- :overlay => true,
339
- :skip_permission_check => false,
340
- :active => false,
341
- :link_options => {},
342
- :overlay_options => {},
343
- :loading_indicator => true
344
- }
345
- options = defaults.merge(options)
346
- button = content_tag('div', :class => 'button_with_label' + (options[:active] ? ' active' : '')) do
347
- link = if options[:overlay]
348
- link_to_overlay_window(
349
- render_icon(options[:icon]),
350
- options[:url],
351
- options[:overlay_options],
352
- {
353
- :class => 'icon_button',
354
- :title => options[:title]
355
- }
356
- )
357
- else
358
- link_to options[:url], {:class => "icon_button#{options[:loading_indicator] ? ' please_wait' : nil}", :title => options[:title]}.merge(options[:link_options]) do
359
- render_icon(options[:icon])
360
- end
361
- end
362
- link += content_tag('label', options[:label])
363
- end
364
- if options[:skip_permission_check]
365
- return button
366
- else
367
- if options[:if_permitted_to].blank?
368
- action_controller = options[:url].gsub(/^\//, '').split('/')
369
- options[:if_permitted_to] = [action_controller.last.to_sym, action_controller[0..action_controller.length-2].join('_').to_sym]
370
- end
371
- if permitted_to?(*options[:if_permitted_to])
372
- return button
373
- else
374
- return ""
375
- end
376
- end
377
- end
305
+ # (internal) Renders a select tag for all items in the clipboard
306
+ def clipboard_select_tag(items, html_options = {})
307
+ options = [[t('Please choose'), ""]]
308
+ items.each do |item|
309
+ options << [item.class.to_s == 'Alchemy::Element' ? item.display_name_with_preview_text : item.name, item.id]
310
+ end
311
+ select_tag(
312
+ 'paste_from_clipboard',
313
+ !@page.new_record? && @page.can_have_cells? ? grouped_elements_for_select(items, :id) : options_for_select(options),
314
+ {
315
+ :class => [html_options[:class], 'alchemy_selectbox'].join(' '),
316
+ :style => html_options[:style]
317
+ }
318
+ )
319
+ end
378
320
 
379
- # Renders the Alchemy backend toolbar
380
- #
381
- # == Options
382
- #
383
- # :buttons [Array] # Pass an Array with button options. They will be passed to toolbar_button helper. For options see toolbar_button
384
- # :search [Boolean] # Show searchfield. Default true.
385
- #
386
- def toolbar(options = {})
387
- defaults = {
388
- :buttons => [],
389
- :search => true
390
- }
391
- options = defaults.merge(options)
392
- content_for(:toolbar) do
393
- content = <<-CONTENT
394
- #{options[:buttons].map { |button_options| toolbar_button(button_options) }.join()}
395
- #{render('alchemy/admin/partials/search_form', :url => options[:search_url]) if options[:search]}
396
- CONTENT
397
- content.html_safe
398
- end
399
- end
321
+ # Renders a toolbar button for the Alchemy toolbar
322
+ #
323
+ # == Options:
324
+ #
325
+ # :icon [String] # Icon class. See base.css.sccs for available icons, or make your own.
326
+ # :label [String] # Text for button label.
327
+ # :url [String] # Url for link.
328
+ # :title [String] # Text for title tag.
329
+ # :overlay [Boolean] # Pass true to open the link in a modal overlay window.
330
+ # :overlay_options [Hash] # Overlay options. See link_to_overlay_window helper.
331
+ # :if_permitted_to [Array] # Check permission for button. [:action, :controller]. Exactly how you defined the permission in your +authorization_rules.rb+. Defaults to controller and action from button url.
332
+ # :skip_permission_check [Boolean] # Skip the permission check. Default false. NOT RECOMMENDED!
333
+ # :loading_indicator [Boolean] # Shows the please wait overlay while loading. Default false.
334
+ #
335
+ def toolbar_button(options = {})
336
+ options.symbolize_keys!
337
+ defaults = {
338
+ :overlay => true,
339
+ :skip_permission_check => false,
340
+ :active => false,
341
+ :link_options => {},
342
+ :overlay_options => {},
343
+ :loading_indicator => false
344
+ }
345
+ options = defaults.merge(options)
346
+ button = content_tag('div', :class => 'button_with_label' + (options[:active] ? ' active' : '')) do
347
+ link = if options[:overlay]
348
+ link_to_overlay_window(
349
+ render_icon(options[:icon]),
350
+ options[:url],
351
+ options[:overlay_options],
352
+ {
353
+ :class => 'icon_button',
354
+ :title => options[:title]
355
+ }
356
+ )
357
+ else
358
+ link_to options[:url], {:class => "icon_button#{options[:loading_indicator] ? nil : ' please_wait'}", :title => options[:title]}.merge(options[:link_options]) do
359
+ render_icon(options[:icon])
360
+ end
361
+ end
362
+ link += content_tag('label', options[:label])
363
+ end
364
+ if options[:skip_permission_check]
365
+ return button
366
+ else
367
+ if options[:if_permitted_to].blank?
368
+ action_controller = options[:url].gsub(/^\//, '').split('/')
369
+ options[:if_permitted_to] = [action_controller.last.to_sym, action_controller[0..action_controller.length-2].join('_').to_sym]
370
+ end
371
+ if permitted_to?(*options[:if_permitted_to])
372
+ return button
373
+ else
374
+ return ""
375
+ end
376
+ end
377
+ end
400
378
 
401
- # Renders the row for a resource record in the resources table.
402
- #
403
- # This helper has a nice fallback. If you create a partial for your record then this partial will be rendered.
404
- #
405
- # Otherwise the default +app/views/alchemy/admin/resources/_resource.html.erb+ partial gets rendered.
406
- #
407
- # == Example
408
- #
409
- # For a resource named +Comment+ you can create a partial named +_comment.html.erb+
410
- #
411
- # # app/views/admin/comments/_comment.html.erb
412
- # <tr>
413
- # <td><%= comment.title %></td>
414
- # <td><%= comment.body %></td>
415
- # </tr>
416
- #
417
- # NOTE: Alchemy gives you a local variable named like your resource
418
- #
419
- def render_resources
420
- render resources_instance_variable
421
- rescue ActionView::MissingTemplate
422
- render :partial => 'resource', :collection => resources_instance_variable
423
- end
379
+ # Renders the Alchemy backend toolbar
380
+ #
381
+ # == Options
382
+ #
383
+ # :buttons [Array] # Pass an Array with button options. They will be passed to toolbar_button helper. For options see toolbar_button
384
+ # :search [Boolean] # Show searchfield. Default true.
385
+ #
386
+ def toolbar(options = {})
387
+ defaults = {
388
+ :buttons => [],
389
+ :search => true
390
+ }
391
+ options = defaults.merge(options)
392
+ content_for(:toolbar) do
393
+ content = <<-CONTENT
394
+ #{options[:buttons].map { |button_options| toolbar_button(button_options) }.join()}
395
+ #{render('alchemy/admin/partials/search_form', :url => options[:search_url]) if options[:search]}
396
+ CONTENT
397
+ content.html_safe
398
+ end
399
+ end
424
400
 
425
- # (internal) Used by upload form
426
- def new_asset_path_with_session_information(asset_type)
427
- session_key = Rails.application.config.session_options[:key]
428
- if asset_type == "picture"
429
- alchemy.admin_pictures_path(session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token, :format => :js)
430
- elsif asset_type == "attachment"
431
- alchemy.admin_attachments_path(session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token, :format => :js)
432
- end
433
- end
401
+ # Renders the row for a resource record in the resources table.
402
+ #
403
+ # This helper has a nice fallback. If you create a partial for your record then this partial will be rendered.
404
+ #
405
+ # Otherwise the default +app/views/alchemy/admin/resources/_resource.html.erb+ partial gets rendered.
406
+ #
407
+ # == Example
408
+ #
409
+ # For a resource named +Comment+ you can create a partial named +_comment.html.erb+
410
+ #
411
+ # # app/views/admin/comments/_comment.html.erb
412
+ # <tr>
413
+ # <td><%= comment.title %></td>
414
+ # <td><%= comment.body %></td>
415
+ # </tr>
416
+ #
417
+ # NOTE: Alchemy gives you a local variable named like your resource
418
+ #
419
+ def render_resources
420
+ render :partial => resource_model_name, :collection => resources_instance_variable
421
+ rescue ActionView::MissingTemplate
422
+ render :partial => 'resource', :collection => resources_instance_variable
423
+ end
434
424
 
435
- # Renders a textfield ready to display a datepicker
436
- #
437
- # Uses a HTML5 +input type="date"+ field.
438
- #
439
- # Pass a type as third option to override that. But old browsers hand this as text field anyway. So there is no need to override that.
440
- #
441
- # === Example
442
- #
443
- # <%= alchemy_datepicker(@person, :birthday) %>
444
- #
445
- def alchemy_datepicker(object, method, html_options={})
446
- text_field(object.class.name.underscore.to_sym, method.to_sym, {
447
- :type => 'date',
448
- :class => 'thin_border date',
449
- :value => object.send(method.to_sym).nil? ? nil : l(object.send(method.to_sym), :format => :datepicker)
450
- }.merge(html_options))
451
- end
425
+ # (internal) Used by upload form
426
+ def new_asset_path_with_session_information(asset_type)
427
+ session_key = Rails.application.config.session_options[:key]
428
+ if asset_type == "picture"
429
+ alchemy.admin_pictures_path(session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token, :format => :js)
430
+ elsif asset_type == "attachment"
431
+ alchemy.admin_attachments_path(session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token, :format => :js)
432
+ end
433
+ end
452
434
 
453
- end
454
- end
435
+ # Renders a textfield ready to display a datepicker
436
+ #
437
+ # Uses a HTML5 +input type="date"+ field.
438
+ #
439
+ # Pass a type as third option to override that. But old browsers hand this as text field anyway. So there is no need to override that.
440
+ #
441
+ # === Example
442
+ #
443
+ # <%= alchemy_datepicker(@person, :birthday) %>
444
+ #
445
+ def alchemy_datepicker(object, method, html_options={})
446
+ text_field(object.class.name.underscore.to_sym, method.to_sym, {
447
+ :type => 'date',
448
+ :class => 'thin_border date',
449
+ :value => object.send(method.to_sym).nil? ? nil : l(object.send(method.to_sym), :format => :datepicker)
450
+ }.merge(html_options))
451
+ end
452
+
453
+ end
454
+ end
455
455
  end