alchemy_cms 3.0.4 → 3.1.0.beta1

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -6
  3. data/Gemfile +4 -7
  4. data/README.md +207 -115
  5. data/alchemy_cms.gemspec +10 -9
  6. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +2 -2
  7. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +2 -2
  8. data/app/assets/javascripts/alchemy/alchemy.js +6 -7
  9. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +1 -43
  10. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +1 -1
  11. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -1
  12. data/app/assets/stylesheets/alchemy/buttons.scss +0 -5
  13. data/app/assets/stylesheets/alchemy/dialogs.scss +1 -0
  14. data/app/assets/stylesheets/alchemy/frame.scss +9 -12
  15. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +11 -2
  16. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +9 -1
  17. data/app/controllers/alchemy/admin/attachments_controller.rb +2 -4
  18. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +34 -38
  19. data/app/controllers/alchemy/api/base_controller.rb +19 -0
  20. data/app/controllers/alchemy/api/contents_controller.rb +35 -0
  21. data/app/controllers/alchemy/api/elements_controller.rb +29 -0
  22. data/app/controllers/alchemy/api/pages_controller.rb +32 -0
  23. data/app/controllers/alchemy/contents_controller.rb +1 -0
  24. data/app/controllers/alchemy/elements_controller.rb +5 -2
  25. data/app/controllers/alchemy/pages_controller.rb +4 -1
  26. data/app/controllers/alchemy/pictures_controller.rb +4 -36
  27. data/app/helpers/alchemy/admin/essences_helper.rb +5 -2
  28. data/app/helpers/alchemy/essences_helper.rb +14 -1
  29. data/app/models/alchemy/content.rb +32 -4
  30. data/app/models/alchemy/element.rb +2 -16
  31. data/app/models/alchemy/element/presenters.rb +2 -2
  32. data/app/models/alchemy/essence_file.rb +5 -0
  33. data/app/models/alchemy/essence_picture.rb +12 -8
  34. data/app/models/alchemy/picture.rb +1 -74
  35. data/app/models/alchemy/picture/transformations.rb +249 -0
  36. data/app/serializers/alchemy/content_serializer.rb +3 -10
  37. data/app/serializers/alchemy/element_serializer.rb +6 -3
  38. data/app/serializers/alchemy/legacy_element_serializer.rb +17 -0
  39. data/app/views/alchemy/admin/dashboard/_sites.html.erb +14 -4
  40. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +8 -5
  41. data/app/views/alchemy/admin/pages/edit.html.erb +9 -9
  42. data/app/views/alchemy/admin/pictures/info.html.erb +2 -3
  43. data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
  44. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +8 -7
  45. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +3 -3
  46. data/app/views/alchemy/essences/_essence_date_editor.html.erb +8 -2
  47. data/app/views/alchemy/essences/_essence_date_view.html.erb +10 -8
  48. data/app/views/alchemy/essences/_essence_file_editor.html.erb +48 -53
  49. data/app/views/alchemy/essences/_essence_file_view.html.erb +5 -5
  50. data/app/views/alchemy/essences/_essence_html_editor.html.erb +5 -4
  51. data/app/views/alchemy/essences/_essence_link_editor.html.erb +17 -15
  52. data/app/views/alchemy/essences/_essence_link_view.html.erb +11 -7
  53. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +4 -2
  54. data/app/views/alchemy/essences/_essence_picture_view.html.erb +4 -2
  55. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +5 -4
  56. data/app/views/alchemy/essences/_essence_select_editor.html.erb +22 -32
  57. data/app/views/alchemy/essences/_essence_text_view.html.erb +7 -6
  58. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +1 -1
  59. data/app/views/layouts/alchemy/admin.html.erb +5 -3
  60. data/config/initializers/inflections.rb +3 -0
  61. data/config/initializers/simple_form.rb +1 -1
  62. data/config/locales/alchemy.en.yml +0 -1
  63. data/config/routes.rb +14 -0
  64. data/lib/alchemy/capistrano.rb +71 -0
  65. data/lib/alchemy/engine.rb +0 -3
  66. data/lib/alchemy/essence.rb +1 -1
  67. data/lib/alchemy/permissions.rb +19 -5
  68. data/lib/alchemy/picture_attributes.rb +1 -1
  69. data/lib/alchemy/test_support/auth_helpers.rb +1 -1
  70. data/lib/alchemy/test_support/essence_shared_examples.rb +37 -22
  71. data/lib/alchemy/test_support/integration_helpers.rb +1 -1
  72. data/lib/alchemy/tinymce.rb +21 -4
  73. data/lib/alchemy/upgrader/three_point_one.rb +43 -0
  74. data/lib/alchemy/upgrader/three_point_zero.rb +13 -0
  75. data/lib/alchemy/version.rb +2 -1
  76. data/lib/rails/generators/alchemy/module/module_generator.rb +30 -0
  77. data/lib/rails/generators/alchemy/module/templates/ability.rb.tt +11 -0
  78. data/lib/rails/generators/alchemy/module/templates/controller.rb.tt +2 -0
  79. data/lib/rails/generators/alchemy/module/templates/module_config.rb.tt +15 -0
  80. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +0 -1
  81. data/lib/rails/templates/alchemy.rb +2 -2
  82. data/lib/tasks/alchemy/db.rake +7 -1
  83. data/spec/controllers/admin/attachments_controller_spec.rb +38 -38
  84. data/spec/controllers/admin/base_controller_spec.rb +18 -18
  85. data/spec/controllers/admin/clipboard_controller_spec.rb +23 -18
  86. data/spec/controllers/admin/contents_controller_spec.rb +33 -27
  87. data/spec/controllers/admin/dashboard_controller_spec.rb +14 -14
  88. data/spec/controllers/admin/elements_controller_spec.rb +125 -105
  89. data/spec/controllers/admin/essence_files_controller_spec.rb +6 -7
  90. data/spec/controllers/admin/essence_pictures_controller_spec.rb +52 -42
  91. data/spec/controllers/admin/languages_controller_spec.rb +3 -3
  92. data/spec/controllers/admin/pages_controller_spec.rb +81 -71
  93. data/spec/controllers/admin/pictures_controller_spec.rb +69 -72
  94. data/spec/controllers/admin/resources_controller_spec.rb +5 -5
  95. data/spec/controllers/admin/trash_controller_spec.rb +15 -12
  96. data/spec/controllers/alchemy/admin/tags_controller_spec.rb +8 -8
  97. data/spec/controllers/alchemy/api/contents_controller_spec.rb +73 -0
  98. data/spec/controllers/alchemy/api/elements_controller_spec.rb +69 -0
  99. data/spec/controllers/alchemy/api/pages_controller_spec.rb +86 -0
  100. data/spec/controllers/attachments_controller_spec.rb +8 -8
  101. data/spec/controllers/contents_controller_spec.rb +22 -0
  102. data/spec/controllers/elements_controller_spec.rb +10 -4
  103. data/spec/controllers/messages_controller_spec.rb +35 -34
  104. data/spec/controllers/pages_controller_spec.rb +37 -28
  105. data/spec/controllers/pictures_controller_spec.rb +90 -23
  106. data/spec/dummy/app/models/dummy_user.rb +0 -4
  107. data/spec/dummy/app/views/alchemy/elements/_all_you_can_eat_editor.html.erb +11 -0
  108. data/spec/dummy/config/alchemy/elements.yml +22 -1
  109. data/spec/dummy/config/alchemy/page_layouts.yml +4 -0
  110. data/spec/dummy/config/application.rb +2 -1
  111. data/spec/dummy/config/environments/test.rb +3 -1
  112. data/spec/features/admin/dashboard_spec.rb +41 -6
  113. data/spec/features/admin/language_tree_feature_spec.rb +3 -3
  114. data/spec/features/admin/legacy_page_url_management_spec.rb +1 -1
  115. data/spec/features/admin/link_overlay_spec.rb +7 -7
  116. data/spec/features/admin/locale_select_feature_spec.rb +5 -2
  117. data/spec/features/admin/modules_integration_spec.rb +1 -1
  118. data/spec/features/admin/page_creation_feature_spec.rb +3 -2
  119. data/spec/features/admin/page_editing_feature_spec.rb +66 -79
  120. data/spec/features/admin/picture_library_integration_spec.rb +8 -8
  121. data/spec/features/admin/resources_integration_spec.rb +21 -21
  122. data/spec/features/admin/tinymce_feature_spec.rb +36 -0
  123. data/spec/features/navigation_spec.rb +1 -1
  124. data/spec/features/page_feature_spec.rb +34 -34
  125. data/spec/features/picture_security_spec.rb +4 -4
  126. data/spec/features/security_spec.rb +1 -1
  127. data/spec/features/translation_integration_spec.rb +7 -7
  128. data/spec/helpers/admin/base_helper_spec.rb +51 -49
  129. data/spec/helpers/admin/contents_helper_spec.rb +11 -11
  130. data/spec/helpers/admin/elements_helper_spec.rb +20 -17
  131. data/spec/helpers/admin/essences_helper_spec.rb +42 -11
  132. data/spec/helpers/admin/navigation_helper_spec.rb +64 -54
  133. data/spec/helpers/admin/pages_helper_spec.rb +10 -10
  134. data/spec/helpers/admin/tags_helper_spec.rb +16 -16
  135. data/spec/helpers/base_helper_spec.rb +11 -11
  136. data/spec/helpers/elements_block_helper_spec.rb +24 -24
  137. data/spec/helpers/elements_helper_spec.rb +46 -46
  138. data/spec/helpers/essences_helper_spec.rb +90 -17
  139. data/spec/helpers/pages_helper_spec.rb +53 -53
  140. data/spec/helpers/picture_url_helpers_spec.rb +6 -6
  141. data/spec/helpers/url_helper_spec.rb +32 -32
  142. data/spec/libraries/config_spec.rb +9 -9
  143. data/spec/libraries/controller_actions_spec.rb +14 -14
  144. data/spec/libraries/i18n_spec.rb +6 -6
  145. data/spec/libraries/kaminari/scoped_pagination_url_helper_spec.rb +4 -4
  146. data/spec/libraries/modules_spec.rb +4 -4
  147. data/spec/libraries/mount_point_spec.rb +13 -13
  148. data/spec/libraries/page_layout_spec.rb +24 -24
  149. data/spec/libraries/permissions_spec.rb +97 -80
  150. data/spec/libraries/resource_spec.rb +37 -37
  151. data/spec/libraries/resources_helper_spec.rb +19 -19
  152. data/spec/libraries/shell_spec.rb +17 -17
  153. data/spec/libraries/template_tracker_spec.rb +14 -14
  154. data/spec/libraries/tinymce_spec.rb +8 -8
  155. data/spec/libraries/userstamp_spec.rb +2 -2
  156. data/spec/mailers/messages_spec.rb +4 -4
  157. data/spec/models/attachment_spec.rb +86 -30
  158. data/spec/models/cell_spec.rb +10 -10
  159. data/spec/models/content_spec.rb +106 -46
  160. data/spec/models/element_spec.rb +94 -115
  161. data/spec/models/essence_date_spec.rb +1 -1
  162. data/spec/models/essence_file_spec.rb +4 -4
  163. data/spec/models/essence_picture_spec.rb +56 -25
  164. data/spec/models/essence_richtext_spec.rb +1 -1
  165. data/spec/models/essence_text_spec.rb +7 -7
  166. data/spec/models/language_spec.rb +12 -12
  167. data/spec/models/legacy_page_url_spec.rb +2 -2
  168. data/spec/models/message_spec.rb +12 -5
  169. data/spec/models/page_spec.rb +259 -235
  170. data/spec/models/picture_spec.rb +72 -166
  171. data/spec/models/site_spec.rb +41 -41
  172. data/spec/models/tag_spec.rb +7 -7
  173. data/spec/routing/api_routing_spec.rb +150 -0
  174. data/spec/routing/routing_spec.rb +28 -28
  175. data/spec/spec_helper.rb +6 -5
  176. data/spec/support/hint_examples.rb +5 -5
  177. data/spec/support/transformation_examples.rb +173 -0
  178. data/spec/tasks/helpers_spec.rb +29 -29
  179. data/spec/views/essences/essence_boolean_editor_spec.rb +32 -0
  180. data/spec/views/essences/essence_boolean_view_spec.rb +2 -2
  181. data/spec/views/essences/essence_date_view_spec.rb +1 -1
  182. data/spec/views/essences/essence_link_view_spec.rb +11 -0
  183. data/spec/views/essences/essence_picture_view_spec.rb +56 -11
  184. data/spec/views/essences/essence_richtext_view_spec.rb +12 -0
  185. data/spec/views/essences/essence_text_view_spec.rb +12 -0
  186. data/vendor/assets/javascripts/tinymce/langs/de.js +20 -2
  187. data/vendor/assets/javascripts/tinymce/langs/fr.js +14 -1
  188. data/vendor/assets/javascripts/tinymce/langs/nl.js +22 -4
  189. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +1 -1
  190. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +1 -1
  191. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +1 -1
  192. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +1 -1
  193. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +1 -1
  194. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +1 -1
  195. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +1 -1
  196. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +1 -1
  197. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +1 -1
  198. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +1 -1
  199. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +1 -1
  200. data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +1 -1
  201. data/vendor/assets/javascripts/tinymce/tinymce.min.js +11 -10
  202. metadata +72 -42
  203. data/app/views/alchemy/messages/contact_form_mail.es.text.erb +0 -12
  204. data/config/locales/alchemy.es.yml +0 -958
  205. data/config/locales/alchemy.ru.yml +0 -837
  206. data/config/locales/simple_form.es.yml +0 -6
  207. data/config/locales/simple_form.ru.yml +0 -25
  208. data/lib/rails/generators/alchemy/scaffold/files/alchemy.es.yml +0 -31
  209. data/vendor/assets/javascripts/tinymce/langs/es.js +0 -197
  210. data/vendor/assets/javascripts/tinymce/langs/ru.js +0 -197
@@ -0,0 +1,249 @@
1
+ module Alchemy
2
+
3
+ # This concern can extend classes that expose image_file, image_file_width and image_file_height.
4
+ # It provides methods for cropping and resizing.
5
+ #
6
+ module Picture::Transformations
7
+ extend ActiveSupport::Concern
8
+
9
+ # Returns the default centered image mask for a given size.
10
+ # If the mask is bigger than the image, the mask is scaled down
11
+ # so the largest possible part of the image is visible.
12
+ #
13
+ def default_mask(mask_arg)
14
+ mask = mask_arg.dup
15
+ mask[:width] = image_file_width if mask[:width].zero?
16
+ mask[:height] = image_file_height if mask[:height].zero?
17
+
18
+ crop_size = size_when_fitting({width: image_file_width, height: image_file_height}, mask)
19
+ top_left = get_top_left_crop_corner(crop_size)
20
+
21
+ point_and_mask_to_points(top_left, crop_size)
22
+ end
23
+
24
+ # Returns a size value String for the thumbnail used in essence picture editors.
25
+ #
26
+ def thumbnail_size(size_string = "0x0", crop = false)
27
+ size = sizes_from_string(size_string)
28
+
29
+ # only if crop is set do we need to actually parse the size string, otherwise
30
+ # we take the base image size.
31
+ if crop
32
+ size[:width] = get_base_dimensions[:width] if size[:width].zero?
33
+ size[:height] = get_base_dimensions[:height] if size[:height].zero?
34
+ size = reduce_to_image(size)
35
+ else
36
+ size = get_base_dimensions
37
+ end
38
+
39
+ size = size_when_fitting({width: 111, height: 93}, size)
40
+ "#{size[:width]}x#{size[:height]}"
41
+ end
42
+
43
+ # Returns the rendered cropped image. Tries to use the crop_from and crop_size
44
+ # parameters. When they can't be parsed, it just crops from the center.
45
+ #
46
+ def crop(size, crop_from = nil, crop_size = nil, upsample = false)
47
+ raise "No size given!" if size.empty?
48
+ render_to = sizes_from_string(size)
49
+ if crop_from && crop_size
50
+ top_left = point_from_string(crop_from)
51
+ crop_dimensions = sizes_from_string(crop_size)
52
+ xy_crop_resize(render_to, top_left, crop_dimensions, upsample)
53
+ else
54
+ center_crop(render_to, upsample)
55
+ end
56
+ end
57
+
58
+ # Returns the rendered resized image using imagemagick directly.
59
+ #
60
+ def resize(size, upsample = false)
61
+ self.image_file.thumb(upsample ? size : "#{size}>")
62
+ end
63
+
64
+ # Given a string with an x, this function returns a Hash with point
65
+ # :width and :height.
66
+ #
67
+ def sizes_from_string(string = "0x0")
68
+ string = "0x0" if string.nil? || string.empty?
69
+
70
+ raise ArgumentError unless string.match(/(\d*x\d*)/)
71
+
72
+ width, height = string.scan(/(\d*)x(\d*)/)[0].map(&:to_i)
73
+
74
+ width = 0 if width.nil?
75
+ height = 0 if height.nil?
76
+ {
77
+ width: width,
78
+ height: height
79
+ }
80
+ end
81
+
82
+ # Returns true if picture's width is greater than it's height
83
+ #
84
+ def landscape_format?
85
+ image_file.landscape?
86
+ end
87
+ alias_method :landscape?, :landscape_format?
88
+
89
+ # Returns true if picture's width is smaller than it's height
90
+ #
91
+ def portrait_format?
92
+ image_file.portrait?
93
+ end
94
+ alias_method :portrait?, :portrait_format?
95
+
96
+ # Returns true if picture's width and height is equal
97
+ #
98
+ def square_format?
99
+ image_file.aspect_ratio == 1.0
100
+ end
101
+ alias_method :square?, :square_format?
102
+
103
+ # This function returns the :width and :height of the image file
104
+ # as a Hash
105
+ def image_size
106
+ {
107
+ width: image_file_width,
108
+ height: image_file_height
109
+ }
110
+ end
111
+
112
+ # An Image smaller than dimensions
113
+ # can not be cropped to string - unless upsample is true.
114
+ #
115
+ def can_be_cropped_to(string, upsample = false)
116
+ dimensions = sizes_from_string(string)
117
+ return true if upsample
118
+ is_bigger_than(dimensions)
119
+ end
120
+
121
+ # Returns true if the class we're included in has a meaningful render_size attribute
122
+ #
123
+ def render_size?
124
+ self.respond_to?(:render_size) && !self.render_size.nil? && !self.render_size.empty?
125
+ end
126
+
127
+ # Returns true if the class we're included in has a meaningful crop_size attribute
128
+ #
129
+ def crop_size?
130
+ self.respond_to?(:crop_size) && !self.crop_size.nil? && !self.crop_size.empty?
131
+ end
132
+
133
+ private
134
+
135
+ # Given a string with an x, this function return a Hash with key :x and :y
136
+ #
137
+ def point_from_string(string = "0x0")
138
+ string = "0x0" if string.empty?
139
+ raise ArgumentError if !string.match(/(\d*x)|(x\d*)/)
140
+
141
+ x, y = string.scan(/(\d*)x(\d*)/)[0].map(&:to_i)
142
+
143
+ x = 0 if x.nil?
144
+ y = 0 if y.nil?
145
+ {
146
+ x: x,
147
+ y: y
148
+ }
149
+ end
150
+
151
+ # Given dimensions for a possibly destructive crop operation,
152
+ # this function returns the top left corner as a Hash
153
+ # with keys :x, :y
154
+ #
155
+ def get_top_left_crop_corner(dimensions)
156
+ {
157
+ x: (image_file_width - dimensions[:width]) / 2,
158
+ y: (image_file_height - dimensions[:height]) / 2
159
+ }
160
+ end
161
+
162
+ # Gets the base dimensions (the dimensions of the Picture before scaling).
163
+ # If anything is missing, it gets padded with zero (Integer 0).
164
+ # This is the order of precedence: crop_size > image_size
165
+ def get_base_dimensions
166
+ if crop_size?
167
+ sizes_from_string(crop_size)
168
+ else
169
+ image_size
170
+ end
171
+ end
172
+
173
+ # This function takes a target and a base dimensions hash and returns
174
+ # the dimensions of the image when the base dimensions hash fills
175
+ # the target.
176
+ # Aspect ratio will be preserved.
177
+ #
178
+ def size_when_fitting(target, dimensions = get_base_dimensions)
179
+ zoom_x = dimensions[:width].to_f / target[:width]
180
+ zoom_y = dimensions[:height].to_f / target[:height]
181
+
182
+ zoom = [zoom_x, zoom_y].max
183
+ {
184
+ width: (dimensions[:width] / zoom).round.to_i,
185
+ height: (dimensions[:height] / zoom).round.to_i
186
+ }
187
+ end
188
+
189
+ # Given a point as a Hash with :x and :y, and a mask with
190
+ # :width and :height, this function returns the area on the
191
+ # underlying canvas as a Hash of two points
192
+ #
193
+ def point_and_mask_to_points(point, mask)
194
+ {
195
+ x1: point[:x],
196
+ y1: point[:y],
197
+ x2: point[:x] + mask[:width],
198
+ y2: point[:y] + mask[:height],
199
+ }
200
+ end
201
+
202
+ # Converts a dimensions hash to a string of from "20x20"
203
+ #
204
+ def dimensions_to_string(dimensions)
205
+ "#{dimensions[:width]}x#{dimensions[:height]}"
206
+ end
207
+
208
+ # Returns true if both dimensions of the base image are bigger than the dimensions hash.
209
+ #
210
+ def is_bigger_than(dimensions)
211
+ image_file_width > dimensions[:width] && image_file_height > dimensions[:height]
212
+ end
213
+
214
+ # Returns true is one dimension of the base image is smaller than the dimensions hash.
215
+ #
216
+ def is_smaller_than(dimensions)
217
+ !is_bigger_than(dimensions)
218
+ end
219
+
220
+ # Uses imagemagick to make a centercropped thumbnail. Does not scale the image up.
221
+ #
222
+ def center_crop(dimensions, upsample)
223
+ if is_smaller_than(dimensions) && upsample == false
224
+ dimensions = reduce_to_image(dimensions)
225
+ end
226
+ self.image_file.thumb("#{dimensions_to_string(dimensions)}#")
227
+ end
228
+
229
+ # Use imagemagick to custom crop an image. Uses -thumbnail for better performance when resizing.
230
+ #
231
+ def xy_crop_resize(dimensions, top_left, crop_dimensions, upsample)
232
+ crop_argument = "-crop #{dimensions_to_string(crop_dimensions)}"
233
+ crop_argument += "+#{top_left[:x]}+#{top_left[:y]}"
234
+
235
+ resize_argument = "-resize #{dimensions_to_string(dimensions)}"
236
+ resize_argument += ">" unless upsample
237
+ self.image_file.convert "#{crop_argument} #{resize_argument}"
238
+ end
239
+
240
+ # Used when centercropping.
241
+ #
242
+ def reduce_to_image(dimensions)
243
+ {
244
+ width: [dimensions[:width], image_file_width].min,
245
+ height: [dimensions[:height], image_file_height].min
246
+ }
247
+ end
248
+ end
249
+ end
@@ -8,20 +8,13 @@ module Alchemy
8
8
  :element_id,
9
9
  :position,
10
10
  :created_at,
11
- :updated_at
11
+ :updated_at,
12
+ :settings
12
13
 
13
14
  has_one :essence, polymorphic: true
14
15
 
15
16
  def ingredient
16
- case object.essence_type
17
- when 'Alchemy::EssencePicture'
18
- object.essence.picture_url
19
- when 'Alchemy::EssenceFile'
20
- object.essence.attachment_url
21
- else
22
- object.ingredient
23
- end
17
+ object.serialized_ingredient
24
18
  end
25
-
26
19
  end
27
20
  end
@@ -9,9 +9,12 @@ module Alchemy
9
9
  :cell_id,
10
10
  :tag_list,
11
11
  :created_at,
12
- :updated_at
13
-
14
- has_many :contents
12
+ :updated_at,
13
+ :ingredients,
14
+ :content_ids
15
15
 
16
+ def ingredients
17
+ object.contents.collect(&:serialize)
18
+ end
16
19
  end
17
20
  end
@@ -0,0 +1,17 @@
1
+ module Alchemy
2
+ class LegacyElementSerializer < ActiveModel::Serializer
3
+ self.root = false
4
+
5
+ attributes :id,
6
+ :name,
7
+ :position,
8
+ :page_id,
9
+ :cell_id,
10
+ :tag_list,
11
+ :created_at,
12
+ :updated_at
13
+
14
+ has_many :contents
15
+
16
+ end
17
+ end
@@ -1,10 +1,20 @@
1
- <div class="widget">
2
- <h2><%= Alchemy::Site.model_name.human(:count => 2) %>:</h2>
1
+ <div class="widget sites">
2
+ <h2><%= Alchemy::Site.model_name.human(count: 2) %>:</h2>
3
3
  <table>
4
4
  <% @sites.each do |site| %>
5
- <tr class="<%= cycle('even', 'odd', :name => 'sites') %>">
5
+ <tr class="<%= cycle('even', 'odd', name: 'sites') %>">
6
6
  <td>
7
- <%= link_to_unless(site == Alchemy::Site.current, site.name, login_url(:protocol => 'http://', :host => site.host, :user => {:login => current_alchemy_user.login}), :target => '_blank') %>
7
+ <% if alchemy.respond_to?(:login_url) %>
8
+ <%= link_to_unless site == Alchemy::Site.current,
9
+ site.name,
10
+ alchemy.login_url(
11
+ protocol: 'http://',
12
+ host: site.host,
13
+ user: {login: current_alchemy_user.try(:login)}
14
+ ), target: '_blank' %>
15
+ <% else %>
16
+ <%= site.name %>
17
+ <% end %>
8
18
  </td>
9
19
  <td><small><%= site.host %></small></td>
10
20
  </tr>
@@ -35,12 +35,15 @@
35
35
  Alchemy.ImageLoader('#jscropper .thumbnail_background');
36
36
  $('#imageToCrop').load(function() {
37
37
  Alchemy.ImageCropper.init(
38
- [<%= @initial_box[:x1] %>, <%= @initial_box[:y1] %>, <%= @initial_box[:x2] %>, <%= @initial_box[:y2] %>],
39
- <%= @size_x %>,
40
- <%= @size_y %>,
41
- [<%= @default_box[:x1] %>, <%= @default_box[:y1] %>, <%= @default_box[:x2] %>, <%= @default_box[:y2] %>],
38
+ <%= @initial_box.values.to_json %>,
39
+ <% if @essence_picture.can_be_cropped_to("#{@min_size[:width]}x#{@min_size[:height]}") %>
40
+ <%= @min_size.values.to_json %>,
41
+ <% else %>
42
+ <%= false %>,
43
+ <% end %>
44
+ <%= @default_box.values.to_json %>,
42
45
  <%= @ratio %>,
43
- [<%= @picture.image_file_width %>, <%= @picture.image_file_height %>]
46
+ <%= @picture.image_size.values.to_json %>
44
47
  );
45
48
  });
46
49
  </script>
@@ -70,15 +70,15 @@
70
70
  <% end %>
71
71
  <label><%= _t(:page_properties) %></label>
72
72
  </div>
73
- <% if can?(:publish, @page) && !@page.layoutpage? %>
74
- <div class="button_with_label">
75
- <%= form_tag alchemy.publish_admin_page_path(@page), id: 'publish_page_form' do %>
76
- <%= button_tag class: 'icon_button', title: _t(:explain_publishing) do %>
77
- <%= render_icon('publish') %>
78
- <% end %>
79
- <label><%= _t("Publish page") %></label>
80
- <% end %>
81
- </div>
73
+ <% if configuration(:cache_pages) && !@page.layoutpage? %>
74
+ <div class="button_with_label">
75
+ <%= form_tag alchemy.publish_admin_page_path(@page), id: 'publish_page_form' do %>
76
+ <button class="icon_button" title="<%= _t(:explain_publishing) %>">
77
+ <%= render_icon('publish') %>
78
+ </button>
79
+ <label><%= _t("Publish page") %></label>
80
+ <% end %>
81
+ </div>
82
82
  <% end %>
83
83
  <div class="toolbar_spacer"></div>
84
84
  <div class="select_with_label">
@@ -25,9 +25,8 @@
25
25
  <ul>
26
26
  <% essence_pictures.group_by(&:element).each do |element, essence_pictures| %>
27
27
  <li class="<%= cycle('even', 'odd') %>">
28
- <% page_link = link_to element.display_name_with_preview_text, edit_admin_page_path(page, :anchor => "element_#{element.id}") %>
29
- <% pictures = essence_pictures.collect { |e| e.content.name_for_label }.to_sentence %>
30
- <%= _t(:pictures_in_page, :page => page_link, :pictures => pictures) %>
28
+ <%= link_to element.display_name_with_preview_text, edit_admin_page_path(page, :anchor => "element_#{element.id}") %> in
29
+ <%= essence_pictures.collect { |e| e.content.name_for_label }.to_sentence %>
31
30
  </li>
32
31
  <% end %>
33
32
  </ul>
@@ -11,7 +11,7 @@
11
11
  <%= _t(:or_replace_it_with_an_existing_tag) %>
12
12
  <% end %>
13
13
  <div class="input tags">
14
- <label class="control-label"><%= _t('Tags') %></label>
14
+ <label class="control-label">Tags</label>
15
15
  <div class="control_group" id="tags_tag_list">
16
16
  <%= js_filter_field '#tag_list li' %>
17
17
  <ul id="tag_list" class="tags">
@@ -1,11 +1,12 @@
1
1
  <% cache(content) do %>
2
- <div class="content_editor essence_boolean" id="<%= content.dom_id %>">
3
- <input type="hidden" value="0" name="<%= content.form_field_name %>" />
4
- <%= check_box_tag(content.form_field_name, 1,
5
- !content.ingredient.nil? ? content.ingredient : options[:default_value],
6
- :class => html_options[:class],
7
- :style => html_options[:style]
8
- ) %>
2
+ <div class="content_editor essence_boolean" id="<%= content.dom_id %>" data-content-id="<%= content.id %>">
3
+ <input type="hidden" value="0" name="<%= content.form_field_name %>">
4
+ <%= check_box_tag content.form_field_name, 1,
5
+ content.ingredient.presence || content_settings_value(
6
+ content, :default_value,
7
+ local_assigns.fetch(:options, {})),
8
+ class: local_assigns.fetch(:html_options, {})[:class],
9
+ style: local_assigns.fetch(:html_options, {})[:style] %>
9
10
  <label for="<%= content.form_field_id %>" style="display: inline">
10
11
  <%= render_content_name(content) %>
11
12
  <%= delete_content_link(content) %>
@@ -1,3 +1,3 @@
1
- <% cache(content) do %>
2
- <%= _t(content.ingredient) %>
3
- <% end %>
1
+ <%- cache(content) do -%>
2
+ <%= _t(content.ingredient) -%>
3
+ <%- end -%>
@@ -1,13 +1,19 @@
1
- <div class="content_editor essence_date" id="<%= content.dom_id %>">
1
+ <% cache(content) do %>
2
+ <div class="content_editor essence_date" id="<%= content.dom_id %>" data-content-id="<%= content.id %>">
2
3
  <%= label_and_remove_link(content) %>
3
4
  <%= alchemy_datepicker(
4
5
  content.essence, :date, {
5
6
  name: content.form_field_name,
6
7
  id: content.form_field_id,
7
- value: options[:default_value]
8
+ value: content_settings_value(
9
+ content,
10
+ :default_value,
11
+ local_assigns.fetch(:options, {})
12
+ )
8
13
  }
9
14
  ) %>
10
15
  <label for="<%= content.form_field_id %>" style="cursor: pointer; display: inline; display: inline-block; position: relative; top: 3px; margin: 0;">
11
16
  <span class="ui-icon ui-icon-calendar"></span>
12
17
  </label>
13
18
  </div>
19
+ <% end %>