alchemy_cms 3.4.2 → 3.5.0.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 (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