alchemy_cms 3.4.2 → 3.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +9 -3
  3. data/.teatro.yml +1 -0
  4. data/.travis.yml +14 -17
  5. data/CHANGELOG.md +44 -6
  6. data/Gemfile +7 -4
  7. data/README.md +60 -10
  8. data/Rakefile +1 -1
  9. data/alchemy_cms.gemspec +5 -8
  10. data/app/assets/javascripts/alchemy/admin.js +2 -0
  11. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -0
  12. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +1 -0
  13. data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +1 -1
  14. data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +9 -7
  15. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +1 -0
  16. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +11 -7
  17. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +1 -1
  18. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +8 -3
  19. data/app/assets/javascripts/alchemy/alchemy.tooltips.coffee +10 -0
  20. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +104 -73
  21. data/app/assets/stylesheets/alchemy/_defaults.scss +1 -4
  22. data/app/assets/stylesheets/alchemy/_extends.scss +13 -35
  23. data/app/assets/stylesheets/alchemy/_mixins.scss +82 -18
  24. data/app/assets/stylesheets/alchemy/_variables.scss +21 -8
  25. data/app/assets/stylesheets/alchemy/admin.scss +4 -0
  26. data/app/assets/stylesheets/alchemy/archive.scss +8 -12
  27. data/app/assets/stylesheets/alchemy/attachments.scss +39 -0
  28. data/app/assets/stylesheets/alchemy/base.scss +26 -15
  29. data/app/assets/stylesheets/alchemy/buttons.scss +59 -31
  30. data/app/assets/stylesheets/alchemy/dashboard.scss +3 -3
  31. data/app/assets/stylesheets/alchemy/dialogs.scss +10 -8
  32. data/app/assets/stylesheets/alchemy/elements.scss +65 -41
  33. data/app/assets/stylesheets/alchemy/errors.scss +7 -0
  34. data/app/assets/stylesheets/alchemy/flash.scss +1 -1
  35. data/app/assets/stylesheets/alchemy/form_fields.scss +0 -37
  36. data/app/assets/stylesheets/alchemy/forms.scss +18 -27
  37. data/app/assets/stylesheets/alchemy/frame.scss +104 -204
  38. data/app/assets/stylesheets/alchemy/hints.scss +62 -0
  39. data/app/assets/stylesheets/alchemy/icon-font.scss +2 -1
  40. data/app/assets/stylesheets/alchemy/icons.scss +9 -4
  41. data/app/assets/stylesheets/alchemy/image_library.scss +6 -6
  42. data/app/assets/stylesheets/alchemy/jquery-ui.scss +6 -4
  43. data/app/assets/stylesheets/alchemy/lists.scss +0 -1
  44. data/app/assets/stylesheets/alchemy/menubar.scss +3 -4
  45. data/app/assets/stylesheets/alchemy/modules.scss +0 -6
  46. data/app/assets/stylesheets/alchemy/navigation.scss +242 -0
  47. data/app/assets/stylesheets/alchemy/pagination.scss +3 -3
  48. data/app/assets/stylesheets/alchemy/print.scss +1 -0
  49. data/app/assets/stylesheets/alchemy/resource_info.scss +45 -0
  50. data/app/assets/stylesheets/alchemy/search.scss +72 -1
  51. data/app/assets/stylesheets/alchemy/selects.scss +38 -44
  52. data/app/assets/stylesheets/alchemy/sitemap.scss +89 -79
  53. data/app/assets/stylesheets/alchemy/tables.scss +6 -10
  54. data/app/assets/stylesheets/alchemy/toolbar.scss +7 -36
  55. data/app/assets/stylesheets/alchemy/upload.scss +12 -3
  56. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +6 -3
  57. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +58 -170
  58. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
  59. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
  60. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +124 -148
  61. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
  62. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
  63. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +426 -144
  64. data/app/controllers/alchemy/admin/attachments_controller.rb +24 -16
  65. data/app/controllers/alchemy/admin/clipboard_controller.rb +1 -1
  66. data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
  67. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +9 -8
  68. data/app/controllers/alchemy/admin/layoutpages_controller.rb +1 -0
  69. data/app/controllers/alchemy/admin/pages_controller.rb +2 -2
  70. data/app/controllers/alchemy/admin/resources_controller.rb +2 -2
  71. data/app/controllers/alchemy/admin/tags_controller.rb +1 -1
  72. data/app/controllers/alchemy/api/pages_controller.rb +16 -0
  73. data/app/controllers/alchemy/messages_controller.rb +1 -1
  74. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -2
  75. data/app/helpers/alchemy/admin/attachments_helper.rb +11 -0
  76. data/app/helpers/alchemy/admin/base_helper.rb +37 -4
  77. data/app/helpers/alchemy/admin/contents_helper.rb +11 -4
  78. data/app/helpers/alchemy/admin/elements_helper.rb +0 -19
  79. data/app/helpers/alchemy/admin/essences_helper.rb +7 -30
  80. data/app/helpers/alchemy/admin/navigation_helper.rb +13 -51
  81. data/app/helpers/alchemy/admin/pages_helper.rb +21 -16
  82. data/app/helpers/alchemy/admin/pictures_helper.rb +9 -0
  83. data/app/helpers/alchemy/deprecated_pages_helper.rb +54 -0
  84. data/app/helpers/alchemy/essences_helper.rb +1 -1
  85. data/app/helpers/alchemy/pages_helper.rb +8 -109
  86. data/app/helpers/alchemy/url_helper.rb +8 -13
  87. data/app/models/alchemy/attachment.rb +7 -4
  88. data/app/models/alchemy/cell.rb +2 -2
  89. data/app/models/alchemy/content.rb +2 -2
  90. data/app/models/alchemy/content/factory.rb +12 -9
  91. data/app/models/alchemy/element.rb +6 -3
  92. data/app/models/alchemy/essence_file.rb +1 -1
  93. data/app/models/alchemy/essence_picture.rb +37 -47
  94. data/app/models/alchemy/essence_picture_view.rb +8 -1
  95. data/app/models/alchemy/folded_page.rb +3 -2
  96. data/app/models/alchemy/legacy_page_url.rb +3 -3
  97. data/app/models/alchemy/page.rb +50 -5
  98. data/app/models/alchemy/page/fixed_attributes.rb +63 -0
  99. data/app/models/alchemy/page/page_elements.rb +10 -7
  100. data/app/models/alchemy/page/page_natures.rb +19 -0
  101. data/app/models/alchemy/picture.rb +1 -0
  102. data/app/models/alchemy/picture/transformations.rb +1 -1
  103. data/app/models/alchemy/picture/url.rb +82 -0
  104. data/app/serializers/alchemy/page_tree_serializer.rb +29 -8
  105. data/app/views/alchemy/_edit_mode.html.erb +2 -0
  106. data/app/views/alchemy/_menubar.html.erb +1 -1
  107. data/app/views/alchemy/_preview_mode_code.html.erb +6 -0
  108. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -1
  109. data/app/views/alchemy/admin/attachments/_attachment.html.erb +25 -5
  110. data/app/views/alchemy/admin/attachments/_replace_button.html.erb +26 -0
  111. data/app/views/alchemy/admin/attachments/index.html.erb +1 -1
  112. data/app/views/alchemy/admin/attachments/show.html.erb +52 -0
  113. data/app/views/alchemy/admin/elements/_element_header.html.erb +6 -3
  114. data/app/views/alchemy/admin/elements/create.js.erb +0 -2
  115. data/app/views/alchemy/admin/elements/trash.js.erb +0 -1
  116. data/app/views/alchemy/admin/elements/update.js.erb +0 -2
  117. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -4
  118. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +1 -1
  119. data/app/views/alchemy/admin/languages/index.html.erb +1 -0
  120. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +26 -27
  121. data/app/views/alchemy/admin/layoutpages/edit.html.erb +1 -1
  122. data/app/views/alchemy/admin/pages/_form.html.erb +13 -40
  123. data/app/views/alchemy/admin/pages/_locked_page.html.erb +1 -1
  124. data/app/views/alchemy/admin/pages/_page.html.erb +119 -61
  125. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +4 -2
  126. data/app/views/alchemy/admin/pages/_page_infos.html.erb +12 -12
  127. data/app/views/alchemy/admin/pages/_page_status.html.erb +1 -1
  128. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +35 -0
  129. data/app/views/alchemy/admin/pages/edit.html.erb +13 -2
  130. data/app/views/alchemy/admin/pages/index.html.erb +3 -8
  131. data/app/views/alchemy/admin/pages/info.html.erb +15 -2
  132. data/app/views/alchemy/admin/pages/sort.js.erb +1 -1
  133. data/app/views/alchemy/admin/pages/update.js.erb +1 -14
  134. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +12 -8
  135. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +4 -4
  136. data/app/views/alchemy/admin/partials/_search_form.html.erb +1 -1
  137. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +9 -6
  138. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -1
  139. data/app/views/alchemy/admin/pictures/_picture.html.erb +1 -6
  140. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -6
  141. data/app/views/alchemy/admin/pictures/index.html.erb +1 -1
  142. data/app/views/alchemy/admin/pictures/show.html.erb +1 -6
  143. data/app/views/alchemy/admin/uploader/_button.html.erb +4 -4
  144. data/app/views/alchemy/base/500.html.erb +15 -1
  145. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +13 -15
  146. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +1 -3
  147. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -2
  148. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -2
  149. data/app/views/alchemy/essences/_essence_file_editor.html.erb +2 -7
  150. data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -3
  151. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -2
  152. data/app/views/alchemy/essences/_essence_html_view.html.erb +1 -3
  153. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -2
  154. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -2
  155. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +47 -49
  156. data/app/views/alchemy/essences/_essence_picture_view.html.erb +1 -3
  157. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -2
  158. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +1 -3
  159. data/app/views/alchemy/essences/_essence_select_editor.html.erb +27 -29
  160. data/app/views/alchemy/essences/_essence_select_view.html.erb +1 -3
  161. data/app/views/alchemy/essences/_essence_text_editor.html.erb +17 -19
  162. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -2
  163. data/app/views/alchemy/pages/_meta_data.html.erb +9 -0
  164. data/app/views/layouts/alchemy/admin.html.erb +9 -11
  165. data/bin/alchemy +1 -2
  166. data/config/alchemy/config.yml +1 -1
  167. data/config/alchemy/modules.yml +0 -16
  168. data/config/initializers/dragonfly.rb +0 -18
  169. data/config/initializers/mini_profiler.rb +6 -0
  170. data/config/locales/alchemy.de.yml +9 -1
  171. data/config/locales/alchemy.en.yml +7 -1
  172. data/config/locales/alchemy.es.yml +6 -0
  173. data/config/locales/alchemy.fr.yml +2 -0
  174. data/config/locales/alchemy.it.yml +3 -1
  175. data/config/locales/alchemy.nl.yml +2 -0
  176. data/config/locales/alchemy.ru.yml +2 -0
  177. data/config/routes.rb +3 -8
  178. data/db/migrate/20160912223112_add_index_to_alchemy_pages_rgt.rb +9 -0
  179. data/db/migrate/20160927205604_add_foreign_key_indices_and_null_constraints.rb +20 -0
  180. data/db/migrate/20160928080104_add_foreign_keys.rb +27 -0
  181. data/lib/alchemy/admin/locale.rb +4 -3
  182. data/lib/alchemy/engine.rb +2 -4
  183. data/lib/alchemy/errors.rb +9 -2
  184. data/lib/alchemy/forms/builder.rb +8 -0
  185. data/lib/alchemy/modules.rb +20 -19
  186. data/lib/alchemy/permissions.rb +15 -4
  187. data/lib/alchemy/resources_helper.rb +4 -2
  188. data/lib/alchemy/sass_support.rb +9 -0
  189. data/lib/alchemy/seeder.rb +89 -1
  190. data/lib/alchemy/test_support/essence_shared_examples.rb +2 -0
  191. data/lib/alchemy/test_support/factories/attachment_factory.rb +1 -1
  192. data/lib/alchemy/test_support/factories/content_factory.rb +1 -0
  193. data/lib/alchemy/test_support/factories/element_factory.rb +1 -0
  194. data/lib/alchemy/test_support/factories/picture_factory.rb +1 -1
  195. data/lib/alchemy/test_support/fixtures/image.png +0 -0
  196. data/lib/alchemy/tinymce.rb +2 -6
  197. data/lib/alchemy/upgrader.rb +4 -55
  198. data/lib/alchemy/upgrader/tasks/install_dragonfly_config.rb +14 -0
  199. data/lib/alchemy/upgrader/three_point_five.rb +32 -0
  200. data/lib/alchemy/upgrader/three_point_four.rb +2 -8
  201. data/lib/alchemy/upgrader/three_point_one.rb +30 -30
  202. data/lib/alchemy/upgrader/three_point_three.rb +31 -31
  203. data/lib/alchemy/upgrader/three_point_two.rb +25 -25
  204. data/lib/alchemy/upgrader/three_point_zero.rb +59 -59
  205. data/lib/alchemy/version.rb +1 -1
  206. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +1 -1
  207. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +1 -1
  208. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +1 -1
  209. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -3
  210. data/lib/rails/generators/alchemy/install/files/_article_view.html.erb +1 -1
  211. data/lib/rails/generators/alchemy/install/files/application.html.erb +3 -4
  212. data/lib/rails/generators/alchemy/install/install_generator.rb +4 -0
  213. data/lib/rails/generators/alchemy/install/templates/dragonfly.rb.tt +35 -0
  214. data/lib/rails/generators/alchemy/module/module_generator.rb +1 -1
  215. data/lib/tasks/alchemy/db.rake +6 -0
  216. data/lib/tasks/alchemy/tidy.rake +85 -0
  217. data/lib/tasks/alchemy/upgrade.rake +165 -16
  218. data/vendor/assets/javascripts/clipboard.min.js +7 -0
  219. data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +4 -4
  220. data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +2 -2
  221. data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +29 -14
  222. data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +2 -2
  223. data/vendor/assets/javascripts/tinymce/langs/es.js +2 -2
  224. data/vendor/assets/javascripts/tinymce/langs/fr.js +1 -1
  225. data/vendor/assets/javascripts/tinymce/langs/it.js +1 -1
  226. data/vendor/assets/javascripts/tinymce/langs/nl.js +3 -3
  227. data/vendor/assets/javascripts/tinymce/tinymce.min.js +15 -12
  228. metadata +44 -88
  229. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/readme.md +0 -1
  230. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.eot +0 -0
  231. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.eot +0 -0
  232. data/app/assets/stylesheets/tinymce/skins/alchemy/img/wline.gif +0 -0
  233. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.ie7.min.css +0 -1
  234. data/app/controllers/alchemy/pictures_controller.rb +0 -97
  235. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +0 -8
  236. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +0 -1
  237. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +0 -1
  238. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +0 -1
  239. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +0 -1
  240. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +0 -1
  241. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +0 -1
  242. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +0 -1
  243. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +0 -1
  244. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +0 -1
  245. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +0 -1
  246. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +0 -1
  247. data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +0 -1
@@ -161,6 +161,7 @@ it:
161
161
  aliases: Separa i domini aggiuntivi con uno spazio od un ritorno a capo.
162
162
 
163
163
  anchor: 'Collegamento'
164
+ attribute_fixed: Il valore non può essere modificato
164
165
  back: 'indietro'
165
166
  create_tree_as_new_language: "Crea una nuova struttura della lingua per %{language}"
166
167
  locked_pages: "Pagine attive"
@@ -417,7 +418,7 @@ it:
417
418
  login: "login"
418
419
  logout: "logout"
419
420
  mail_to: "Destinatario"
420
- main_content: "Contanuto principale"
421
+ main_content: "Contenuto principale"
421
422
  male: "Maschio"
422
423
  me: "Me"
423
424
  medium_thumbnails: "Thumbnail di meda dimensione"
@@ -511,6 +512,7 @@ it:
511
512
  rename_file: "Rinomina questo file."
512
513
  rename: "Rinomina"
513
514
  replace: sostituisci
515
+ replace_file: Sostituire il file
514
516
  'Replaced Tag': "Il tag '%{old_tag}' è stato sostiuito con '%{new_tag}'"
515
517
  resources:
516
518
  relation_select:
@@ -160,6 +160,7 @@ nl:
160
160
  aliases: Specificeer andere domeinen gescheiden met witte ruimte of lege regel
161
161
 
162
162
  anchor: 'Anchor'
163
+ attribute_fixed: Waarde kan niet worden gewijzigd
163
164
  back: 'back'
164
165
  create_tree_as_new_language: "%{language} aanmaken als nieuwe boomstructuur"
165
166
  locked_pages: "Actieve pagina's"
@@ -505,6 +506,7 @@ nl:
505
506
  rename_file: "Dit bestand hernoemen."
506
507
  rename: hernoemen
507
508
  replace: vervangen
509
+ replace_file: Vervang file
508
510
  'Replaced Tag': "De tag '%{old_tag}' wordt door de tag '%{new_tag}' vervangen"
509
511
  resources:
510
512
  relation_select:
@@ -160,6 +160,7 @@ ru:
160
160
  aliases: Разделяйте дополнительные домены с помощью пробелов или переходом на новую строку.
161
161
 
162
162
  anchor: 'Анкор'
163
+ attribute_fixed: Значение не может быть изменен
163
164
  back: 'назад'
164
165
  create_tree_as_new_language: "Создать дерево языка %{language}"
165
166
  locked_pages: "Активные страницы"
@@ -507,6 +508,7 @@ ru:
507
508
  rename_file: "Свойства файла"
508
509
  rename: "Переименовать"
509
510
  replace: "Заменить"
511
+ replace_file: "Заменить файл"
510
512
  'Replaced Tag': "Метка '%{old_tag}' заменена на '%{new_tag}'"
511
513
  resources:
512
514
  relation_select:
@@ -124,14 +124,6 @@ Alchemy::Engine.routes.draw do
124
124
  get '/attachment/:id/show' => 'attachments#show',
125
125
  as: :show_attachment
126
126
 
127
- # Picture urls
128
- get "/pictures/:id/show(/:size)(/:crop)(/:crop_from/:crop_size)(/:quality)/:name.:format" => 'pictures#show',
129
- as: :show_picture
130
- get '/pictures/:id/zoom/:name.:format' => 'pictures#zoom',
131
- as: :zoom_picture
132
- get "/pictures/:id/thumbnails(/:size)(/:crop)(/:crop_from/:crop_size)/:name.:format" => 'pictures#thumbnail',
133
- as: :thumbnail, :defaults => {format: 'png', name: "thumbnail"}
134
-
135
127
  resources :messages, only: [:index, :new, :create]
136
128
  resources :elements, only: :show
137
129
  resources :contents, only: :show
@@ -147,6 +139,9 @@ Alchemy::Engine.routes.draw do
147
139
  resources :pages, only: [:index] do
148
140
  get 'elements' => 'elements#index', as: 'elements'
149
141
  get 'elements/:named' => 'elements#index', as: 'named_elements'
142
+ collection do
143
+ get :nested
144
+ end
150
145
  end
151
146
 
152
147
  get '/pages/*urlname(.:format)' => 'pages#show', as: 'page'
@@ -0,0 +1,9 @@
1
+ class AddIndexToAlchemyPagesRgt < ActiveRecord::Migration
2
+ def up
3
+ add_index :alchemy_pages, :rgt
4
+ end
5
+
6
+ def down
7
+ remove_index :alchemy_pages, :rgt
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ class AddForeignKeyIndicesAndNullConstraints < ActiveRecord::Migration
2
+ def change
3
+ change_column_null :alchemy_cells, :page_id, false, 0
4
+ change_column_null :alchemy_contents, :element_id, false, 0
5
+ change_column_null :alchemy_contents, :essence_id, false, 0
6
+ change_column_null :alchemy_contents, :essence_type, false, 'Alchemy::EssenceText'
7
+ change_column_null :alchemy_elements, :page_id, false, 0
8
+ change_column_null :alchemy_folded_pages, :page_id, false, 0
9
+ change_column_null :alchemy_folded_pages, :user_id, false, 0
10
+ change_column_null :alchemy_languages, :site_id, false, 0
11
+
12
+ add_index :alchemy_cells, :page_id
13
+ add_index :alchemy_contents, [:essence_id, :essence_type], unique: true
14
+ add_index :alchemy_elements, :cell_id
15
+ add_index :alchemy_essence_files, :attachment_id
16
+ add_index :alchemy_essence_pictures, :picture_id
17
+ add_index :alchemy_folded_pages, [:page_id, :user_id], unique: true
18
+ add_index :alchemy_legacy_page_urls, :page_id
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ class AddForeignKeys < ActiveRecord::Migration
2
+ def change
3
+ add_foreign_key :alchemy_cells, :alchemy_pages,
4
+ column: :page_id,
5
+ on_update: :cascade,
6
+ on_delete: :cascade,
7
+ name: :alchemy_cells_page_id_fkey
8
+
9
+ add_foreign_key :alchemy_contents, :alchemy_elements,
10
+ column: :element_id,
11
+ on_update: :cascade,
12
+ on_delete: :cascade,
13
+ name: :alchemy_contents_element_id_fkey
14
+
15
+ add_foreign_key :alchemy_elements, :alchemy_pages,
16
+ column: :page_id,
17
+ on_update: :cascade,
18
+ on_delete: :cascade,
19
+ name: :alchemy_elements_page_id_fkey
20
+
21
+ add_foreign_key :alchemy_elements, :alchemy_cells,
22
+ column: :cell_id,
23
+ on_update: :cascade,
24
+ on_delete: :cascade,
25
+ name: :alchemy_elements_cell_id_fkey
26
+ end
27
+ end
@@ -38,8 +38,8 @@ module Alchemy
38
38
  # * the locale of the browser
39
39
  #
40
40
  def available_locale
41
- locales = [params[:admin_locale], locale_from_user, locale_from_browser].compact
42
- locales.detect { |locale| ::I18n.available_locales.include?(locale.to_sym) }
41
+ locales = [params[:admin_locale], locale_from_user, locale_from_browser].compact.map(&:to_sym)
42
+ locales.detect { |locale| ::I18n.available_locales.include?(locale) }
43
43
  end
44
44
 
45
45
  # Try to get the locale from user settings.
@@ -54,7 +54,8 @@ module Alchemy
54
54
  def user_has_preferred_language?
55
55
  return if !current_alchemy_user
56
56
  current_alchemy_user.respond_to?(:language) &&
57
- current_alchemy_user.language.present?
57
+ current_alchemy_user.language.present? &&
58
+ current_alchemy_user.language.respond_to?(:to_sym)
58
59
  end
59
60
 
60
61
  # Try to get the locale from browser headers.
@@ -1,12 +1,11 @@
1
1
  # Require globally used external libraries
2
- require 'actionpack/page_caching'
3
2
  require 'acts_as_list'
4
3
  require 'acts-as-taggable-on'
5
4
  require 'action_view/dependency_tracker'
6
5
  require 'active_model_serializers'
7
6
  require 'awesome_nested_set'
7
+ require 'bourbon'
8
8
  require 'cancan'
9
- require 'compass-rails'
10
9
  require 'dragonfly'
11
10
  require 'jquery-rails'
12
11
  require 'jquery-ui-rails'
@@ -15,8 +14,6 @@ require 'non-stupid-digest-assets'
15
14
  require 'ransack'
16
15
  require 'request_store'
17
16
  require 'responders'
18
- require 'sass-rails'
19
- require 'sassy-buttons'
20
17
  require 'simple_form'
21
18
  require 'select2-rails'
22
19
  require 'turbolinks'
@@ -46,6 +43,7 @@ require_relative './page_layout'
46
43
  require_relative './paths'
47
44
  require_relative './permissions'
48
45
  require_relative './picture_attributes'
46
+ require_relative './sass_support'
49
47
  require_relative './ssl_protection'
50
48
  require_relative './resource'
51
49
  require_relative './tinymce'
@@ -41,8 +41,15 @@ module Alchemy
41
41
  end
42
42
  end
43
43
 
44
- class MissingImageFileError < StandardError
45
- # Raised if calling +image_file+ on a Picture object returns nil.
44
+ # Raised if calling +image_file+ on a Picture object returns nil.
45
+ class MissingImageFileError < StandardError; end
46
+
47
+ # Raised if calling +image_file+ on a Picture object returns nil.
48
+ class WrongImageFormatError < StandardError
49
+ def message
50
+ allowed_filetypes = Alchemy::Picture.allowed_filetypes.map(&:upcase).to_sentence
51
+ "Requested image format is not one of allowed filetypes (#{allowed_filetypes})."
52
+ end
46
53
  end
47
54
 
48
55
  class NotMountedError < StandardError
@@ -5,6 +5,14 @@ module Alchemy
5
5
  #
6
6
  def input(attribute_name, options = {}, &block)
7
7
  options[:wrapper] = :alchemy
8
+
9
+ if object.respond_to?(:attribute_fixed?) && object.attribute_fixed?(attribute_name)
10
+ options[:disabled] = true
11
+ options[:input_html] = options.fetch(:input_html, {}).merge(
12
+ 'data-alchemy-tooltip' => Alchemy.t(:attribute_fixed, attribute_name)
13
+ )
14
+ end
15
+
8
16
  super
9
17
  end
10
18
 
@@ -22,7 +22,7 @@ module Alchemy
22
22
  # }
23
23
  #
24
24
  def self.register_module(module_definition)
25
- @@alchemy_modules << module_definition.stringify_keys
25
+ @@alchemy_modules << module_definition.deep_stringify_keys
26
26
  end
27
27
 
28
28
  # Get the module definition for given module name
@@ -30,46 +30,47 @@ module Alchemy
30
30
  # You can also pass a hash of an module definition.
31
31
  # It then tries to find the module defintion from controller name and action name
32
32
  #
33
- def module_definition_for(name)
34
- case name
33
+ def module_definition_for(name_or_params)
34
+ case name_or_params
35
35
  when String
36
- alchemy_modules.detect { |p| p['name'] == name }
36
+ alchemy_modules.detect { |m| m['name'] == name_or_params }
37
37
  when Hash
38
+ name_or_params.stringify_keys!
38
39
  alchemy_modules.detect do |alchemy_module|
39
- definition_from_subnavi(alchemy_module, name.symbolize_keys)
40
+ module_navi = alchemy_module.fetch('navigation', {})
41
+ definition_from_mainnavi(module_navi, name_or_params) ||
42
+ definition_from_subnavi(module_navi, name_or_params)
40
43
  end
41
44
  else
42
- raise ArgumentError, "Could not find module definition for #{name}"
45
+ raise ArgumentError, "Could not find module definition for #{name_or_params}"
43
46
  end
44
47
  end
45
48
 
46
49
  private
47
50
 
48
- def alchemy_module_navigation(alchemy_module)
49
- alchemy_module.stringify_keys!
50
- alchemy_module.fetch('navigation', {}).stringify_keys
51
+ def definition_from_mainnavi(module_navi, params)
52
+ controller_matches?(module_navi, params) && action_matches?(module_navi, params)
51
53
  end
52
54
 
53
- def definition_from_subnavi(alchemy_module, name)
54
- module_navi = alchemy_module_navigation(alchemy_module)
55
+ def definition_from_subnavi(module_navi, params)
55
56
  subnavi = module_navi['sub_navigation']
56
57
  return if subnavi.nil?
57
58
 
58
- subnavi.map(&:stringify_keys).detect do |sn|
59
- controller_matches?(sn, name) && action_matches?(sn, name)
59
+ subnavi.any? do |navi|
60
+ controller_matches?(navi, params) && action_matches?(navi, params)
60
61
  end
61
62
  end
62
63
 
63
- def controller_matches?(subnavi, name)
64
- remove_slash(subnavi['controller']) == remove_slash(name[:controller])
64
+ def controller_matches?(navi, params)
65
+ remove_slash(navi['controller']) == remove_slash(params['controller'])
65
66
  end
66
67
 
67
- def action_matches?(subnavi, name)
68
- subnavi['action'] == name[:action]
68
+ def action_matches?(navi, params)
69
+ navi['action'] == params['action']
69
70
  end
70
71
 
71
- def remove_slash(name)
72
- name.gsub(/^\//, '')
72
+ def remove_slash(str)
73
+ str.gsub(/^\//, '')
73
74
  end
74
75
  end
75
76
  end
@@ -113,9 +113,9 @@ module Alchemy
113
113
  can :manage, Alchemy::EssenceFile
114
114
  can :manage, Alchemy::EssencePicture
115
115
  can :manage, Alchemy::LegacyPageUrl
116
- can :edit_content, Alchemy::Page
117
116
  can :read, Alchemy::Picture
118
117
  can [:read, :autocomplete], Alchemy::Tag
118
+ can(:edit_content, Alchemy::Page) { |p| p.editable_by?(@user) }
119
119
  end
120
120
  end
121
121
 
@@ -142,15 +142,26 @@ module Alchemy
142
142
  can [
143
143
  :copy,
144
144
  :copy_language_tree,
145
- :create,
146
- :destroy,
147
145
  :flush,
148
146
  :order,
149
- :publish,
150
147
  :sort,
151
148
  :switch_language
152
149
  ], Alchemy::Page
153
150
 
151
+ # Resources which may be locked via template permissions
152
+ #
153
+ # # config/alchemy/page_layouts.yml
154
+ # - name: contact
155
+ # editable_by:
156
+ # - freelancer
157
+ # - admin
158
+ #
159
+ can([
160
+ :create,
161
+ :destroy,
162
+ :publish
163
+ ], Alchemy::Page) { |p| p.editable_by?(@user) }
164
+
154
165
  can :manage, Alchemy::Picture
155
166
  can :manage, Alchemy::Attachment
156
167
  can :manage, Alchemy::Tag
@@ -96,8 +96,10 @@ module Alchemy
96
96
  when 'date', 'datetime'
97
97
  options.merge as: 'string',
98
98
  input_html: {
99
- type: 'date',
100
- value: l(resource_instance_variable.send(attribute[:name]) || Time.current, format: :datepicker)
99
+ type: attribute[:type].to_s,
100
+ value: l(resource_instance_variable.send(attribute[:name]) || Time.current,
101
+ format: "#{attribute[:type]}picker".to_sym
102
+ )
101
103
  }
102
104
  when 'time'
103
105
  options.merge(as: 'time')
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'sassc-rails'
3
+ rescue LoadError, Gem::LoadError
4
+ begin
5
+ require 'sass-rails'
6
+ rescue LoadError, Gem::LoadError
7
+ raise LoadError, "Could not find the `sass-rails` or `sassc-rails` gem for AlchemyCMS! Please add one of them to your project's Gemfile."
8
+ end
9
+ end
@@ -11,7 +11,14 @@ module Alchemy
11
11
  #
12
12
  def seed!
13
13
  create_default_site
14
- create_root_page
14
+ if create_root_page
15
+ try_seed_pages
16
+ elsif page_seeds_file.file?
17
+ desc "Seeding Alchemy pages"
18
+ log "There are already pages present in your database. " \
19
+ "Please use `rake db:reset' if you want to rebuild your database.", :skip
20
+ end
21
+ seed_users if user_seeds_file.file?
15
22
  end
16
23
 
17
24
  protected
@@ -40,9 +47,61 @@ module Alchemy
40
47
  if root.new_record?
41
48
  if root.save!
42
49
  log "Created Alchemy root page."
50
+ return true
43
51
  end
44
52
  else
45
53
  log "Alchemy root page was already present.", :skip
54
+ return false
55
+ end
56
+ end
57
+
58
+ def try_seed_pages
59
+ if page_seeds_file.file?
60
+ seed_pages if contentpages.present?
61
+ seed_layoutpages if layoutpages.present?
62
+ end
63
+ end
64
+
65
+ def seed_pages
66
+ desc "Seeding Alchemy content pages from #{page_seeds_file}"
67
+ if contentpages.length > 1
68
+ abort "The pages seed file must only contain one root page! You have #{contentpages.length}."
69
+ end
70
+
71
+ contentpages.each do |page|
72
+ create_page(page, {
73
+ parent: Alchemy::Page.root,
74
+ language: Alchemy::Language.default,
75
+ language_root: true
76
+ })
77
+ end
78
+ end
79
+
80
+ def seed_layoutpages
81
+ desc "Seeding Alchemy layout pages from #{page_seeds_file}"
82
+ language = Alchemy::Language.default
83
+ layout_root = Alchemy::Page.find_or_create_layout_root_for(language.id)
84
+ layoutpages.each do |page|
85
+ create_page(page, {
86
+ parent: layout_root,
87
+ language: language
88
+ })
89
+ end
90
+ end
91
+
92
+ def seed_users
93
+ desc "Seeding Alchemy users from #{user_seeds_file}"
94
+
95
+ if Alchemy.user_class.exists?
96
+ log "There are already users present in your database. " \
97
+ "Please use `rake db:reset' if you want to rebuild your database.", :skip
98
+ return false
99
+ else
100
+ users = YAML.load_file(user_seeds_file)
101
+ users.each do |draft|
102
+ user = Alchemy.user_class.create!(draft)
103
+ log "Created user: #{user.try(:email) || user.try(:login) || user.id}"
104
+ end
46
105
  end
47
106
  end
48
107
 
@@ -51,6 +110,35 @@ module Alchemy
51
110
  def site_config
52
111
  @_site_config ||= Alchemy::Config.get(:default_site)
53
112
  end
113
+
114
+ def page_seeds_file
115
+ @_page_seeds_file ||= Rails.root.join('db', 'seeds', 'alchemy', 'pages.yml')
116
+ end
117
+
118
+ def page_yml
119
+ @_page_yml ||= YAML.load_file(page_seeds_file)
120
+ end
121
+
122
+ def contentpages
123
+ page_yml.select { |p| !p['layoutpage'] }
124
+ end
125
+
126
+ def layoutpages
127
+ page_yml.select { |p| p['layoutpage'] }
128
+ end
129
+
130
+ def user_seeds_file
131
+ @_user_seeds_file ||= Rails.root.join('db', 'seeds', 'alchemy', 'users.yml')
132
+ end
133
+
134
+ def create_page(draft, attributes = {})
135
+ children = draft.delete('children') || []
136
+ page = Alchemy::Page.create!(draft.merge(attributes))
137
+ log "Created page: #{page.name}"
138
+ children.each do |child|
139
+ create_page(child, parent: page)
140
+ end
141
+ end
54
142
  end
55
143
  end
56
144
  end