alchemy_cms 7.2.7 → 7.3.0

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -14
  3. data/Gemfile +4 -3
  4. data/Rakefile +1 -0
  5. data/alchemy_cms.gemspec +7 -7
  6. data/app/assets/builds/alchemy/admin/print.css +1 -0
  7. data/app/assets/builds/alchemy/admin/print.css.map +1 -0
  8. data/app/assets/builds/alchemy/admin.css +1 -0
  9. data/app/assets/builds/alchemy/admin.css.map +1 -0
  10. data/app/assets/builds/alchemy/welcome.css +1 -0
  11. data/app/assets/builds/alchemy/welcome.css.map +1 -0
  12. data/app/assets/builds/tinymce/skins/content/alchemy/content.css +1 -0
  13. data/app/assets/builds/tinymce/skins/content/alchemy/content.css.map +1 -0
  14. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -0
  15. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +1 -0
  16. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.css +1 -0
  17. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.css.map +1 -0
  18. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -0
  19. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css.map +1 -0
  20. data/app/assets/config/alchemy_manifest.js +1 -5
  21. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +4 -0
  22. data/app/assets/stylesheets/alchemy/{_custom-properties.scss → _custom-properties.css} +28 -25
  23. data/app/assets/stylesheets/alchemy/_deprecated_variables.scss +41 -0
  24. data/app/assets/stylesheets/alchemy/_deprecation.scss +17 -0
  25. data/app/assets/stylesheets/alchemy/_extends.scss +1 -1
  26. data/app/assets/stylesheets/alchemy/_mixins.scss +20 -23
  27. data/app/assets/stylesheets/alchemy/_variables.scss +98 -94
  28. data/app/assets/stylesheets/alchemy/{archive.scss → admin/archive.scss} +23 -23
  29. data/app/assets/stylesheets/alchemy/{attachment-select.scss → admin/attachment-select.scss} +2 -2
  30. data/app/assets/stylesheets/alchemy/{attachments.scss → admin/attachments.scss} +4 -4
  31. data/app/assets/stylesheets/alchemy/{base.scss → admin/base.scss} +9 -9
  32. data/app/assets/stylesheets/alchemy/{buttons.scss → admin/buttons.scss} +3 -3
  33. data/app/assets/stylesheets/alchemy/{clipboard.scss → admin/clipboard.scss} +9 -6
  34. data/app/assets/stylesheets/alchemy/{dashboard.scss → admin/dashboard.scss} +8 -8
  35. data/app/assets/stylesheets/alchemy/{dialogs.scss → admin/dialogs.scss} +20 -20
  36. data/app/assets/stylesheets/alchemy/{elements.scss → admin/elements.scss} +128 -88
  37. data/app/assets/stylesheets/alchemy/{errors.scss → admin/errors.scss} +22 -6
  38. data/app/assets/stylesheets/alchemy/{flash.scss → admin/flash.scss} +3 -3
  39. data/app/assets/stylesheets/alchemy/{flatpickr.scss → admin/flatpickr.scss} +55 -35
  40. data/app/assets/stylesheets/alchemy/{form_fields.scss → admin/form_fields.scss} +8 -6
  41. data/app/assets/stylesheets/alchemy/{forms.scss → admin/forms.scss} +20 -16
  42. data/app/assets/stylesheets/alchemy/{frame.scss → admin/frame.scss} +9 -9
  43. data/app/assets/stylesheets/alchemy/{image_library.scss → admin/image_library.scss} +34 -33
  44. data/app/assets/stylesheets/alchemy/admin/labels.scss +3 -0
  45. data/app/assets/stylesheets/alchemy/{list_filter.scss → admin/list_filter.scss} +4 -4
  46. data/app/assets/stylesheets/alchemy/{lists.scss → admin/lists.scss} +9 -7
  47. data/app/assets/stylesheets/alchemy/{navigation.scss → admin/navigation.scss} +17 -17
  48. data/app/assets/stylesheets/alchemy/{node-select.scss → admin/node-select.scss} +5 -5
  49. data/app/assets/stylesheets/alchemy/{nodes.scss → admin/nodes.scss} +11 -11
  50. data/app/assets/stylesheets/alchemy/{notices.scss → admin/notices.scss} +11 -7
  51. data/app/assets/stylesheets/alchemy/{page-select.scss → admin/page-select.scss} +10 -10
  52. data/app/assets/stylesheets/alchemy/{pagination.scss → admin/pagination.scss} +10 -10
  53. data/app/assets/stylesheets/alchemy/{print.scss → admin/print.scss} +2 -6
  54. data/app/assets/stylesheets/alchemy/{resource_info.scss → admin/resource_info.scss} +6 -7
  55. data/app/assets/stylesheets/alchemy/{search.scss → admin/search.scss} +6 -6
  56. data/app/assets/stylesheets/alchemy/{selects.scss → admin/selects.scss} +46 -39
  57. data/app/assets/stylesheets/alchemy/{shoelace.scss → admin/shoelace.scss} +10 -10
  58. data/app/assets/stylesheets/alchemy/{sitemap.scss → admin/sitemap.scss} +18 -19
  59. data/app/assets/stylesheets/alchemy/{tables.scss → admin/tables.scss} +26 -22
  60. data/app/assets/stylesheets/alchemy/admin/tags.scss +158 -0
  61. data/app/assets/stylesheets/alchemy/{toolbar.scss → admin/toolbar.scss} +10 -10
  62. data/app/assets/stylesheets/alchemy/{typography.scss → admin/typography.scss} +3 -3
  63. data/app/assets/stylesheets/alchemy/{upload.scss → admin/upload.scss} +1 -1
  64. data/app/assets/stylesheets/alchemy/admin.scss +40 -45
  65. data/app/assets/stylesheets/alchemy/welcome.scss +57 -0
  66. data/app/assets/stylesheets/tinymce/skins/content/alchemy/{content.min.scss → content.scss} +5 -4
  67. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/{skin.min.scss → skin.scss} +40 -40
  68. data/app/components/alchemy/admin/resource/action.rb +46 -0
  69. data/app/components/alchemy/admin/resource/cell.rb +34 -0
  70. data/app/components/alchemy/admin/resource/header.rb +46 -0
  71. data/app/components/alchemy/admin/resource/table.rb +153 -0
  72. data/app/components/alchemy/ingredients/datetime_view.rb +2 -2
  73. data/app/controllers/alchemy/admin/base_controller.rb +2 -1
  74. data/app/controllers/alchemy/admin/elements_controller.rb +7 -3
  75. data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +1 -1
  76. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  77. data/app/controllers/alchemy/admin/pictures_controller.rb +2 -2
  78. data/app/controllers/alchemy/admin/resources_controller.rb +2 -2
  79. data/app/controllers/alchemy/base_controller.rb +2 -0
  80. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -11
  81. data/app/decorators/alchemy/ingredient_editor.rb +17 -0
  82. data/app/helpers/alchemy/admin/pages_helper.rb +6 -10
  83. data/app/helpers/alchemy/base_helper.rb +2 -2
  84. data/app/helpers/alchemy/elements_block_helper.rb +13 -1
  85. data/app/helpers/alchemy/pages_helper.rb +2 -2
  86. data/app/javascript/alchemy_admin/components/element_editor.js +23 -31
  87. data/app/javascript/alchemy_admin/components/preview_window.js +2 -3
  88. data/app/javascript/alchemy_admin/picture_selector.js +38 -10
  89. data/app/models/alchemy/attachment.rb +0 -8
  90. data/app/models/alchemy/element/dom_id.rb +1 -0
  91. data/app/models/alchemy/element/element_ingredients.rb +0 -73
  92. data/app/models/alchemy/element/presenters.rb +4 -1
  93. data/app/models/alchemy/element.rb +6 -0
  94. data/app/models/alchemy/elements_repository.rb +2 -2
  95. data/app/models/alchemy/ingredient_validator.rb +10 -0
  96. data/app/models/alchemy/page/page_scopes.rb +1 -1
  97. data/app/models/alchemy/picture.rb +0 -10
  98. data/app/views/alchemy/admin/attachments/_files_list.html.erb +74 -16
  99. data/app/views/alchemy/admin/clipboard/index.html.erb +38 -33
  100. data/app/views/alchemy/admin/dashboard/_dashboard.html.erb +3 -0
  101. data/app/views/alchemy/admin/dashboard/_left_column.html.erb +4 -0
  102. data/app/views/alchemy/admin/dashboard/_right_column.html.erb +9 -0
  103. data/app/views/alchemy/admin/dashboard/_top.html.erb +12 -0
  104. data/app/views/alchemy/admin/dashboard/index.html.erb +1 -25
  105. data/app/views/alchemy/admin/elements/_element.html.erb +1 -2
  106. data/app/views/alchemy/admin/elements/_form.html.erb +1 -1
  107. data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +10 -3
  108. data/app/views/alchemy/admin/ingredients/update.turbo_stream.erb +7 -0
  109. data/app/views/alchemy/admin/languages/_table.html.erb +16 -42
  110. data/app/views/alchemy/admin/nodes/_form.html.erb +1 -1
  111. data/app/views/alchemy/admin/pages/_table.html.erb +92 -27
  112. data/app/views/alchemy/admin/pages/edit.html.erb +6 -8
  113. data/app/views/alchemy/admin/pages/index.html.erb +0 -4
  114. data/app/views/alchemy/admin/pictures/_form.html.erb +14 -12
  115. data/app/views/alchemy/admin/pictures/index.html.erb +1 -11
  116. data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +6 -0
  117. data/app/views/alchemy/admin/resources/_resource_table.html.erb +3 -0
  118. data/app/views/alchemy/admin/resources/_table.html.erb +2 -0
  119. data/app/views/alchemy/admin/resources/index.html.erb +1 -1
  120. data/app/views/alchemy/admin/sites/index.html.erb +1 -1
  121. data/app/views/alchemy/admin/styleguide/index.html.erb +0 -4
  122. data/app/views/alchemy/admin/tags/index.html.erb +15 -14
  123. data/app/views/alchemy/base/403.html.erb +6 -0
  124. data/app/views/alchemy/base/500.html.erb +14 -12
  125. data/app/views/alchemy/ingredients/_datetime_editor.html.erb +13 -11
  126. data/app/views/alchemy/ingredients/_headline_editor.html.erb +29 -22
  127. data/app/views/alchemy/ingredients/_link_editor.html.erb +17 -11
  128. data/app/views/alchemy/ingredients/_page_editor.html.erb +1 -0
  129. data/app/views/alchemy/ingredients/_picture_editor.html.erb +3 -4
  130. data/app/views/alchemy/ingredients/_richtext_editor.html.erb +5 -1
  131. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -1
  132. data/app/views/alchemy/ingredients/_text_editor.html.erb +20 -14
  133. data/app/views/alchemy/ingredients/shared/_picture_css_class.html.erb +6 -0
  134. data/app/views/layouts/alchemy/admin.html.erb +4 -2
  135. data/bin/setup +2 -0
  136. data/bin/start +1 -1
  137. data/bun.lockb +0 -0
  138. data/config/alchemy/config.yml +9 -0
  139. data/config/locales/alchemy.en.yml +8 -29
  140. data/config/routes.rb +22 -22
  141. data/lib/alchemy/config.rb +3 -3
  142. data/lib/alchemy/install/tasks.rb +5 -2
  143. data/lib/alchemy/resources_helper.rb +3 -1
  144. data/lib/alchemy/test_support/capybara_helpers.rb +8 -5
  145. data/lib/alchemy/test_support/shared_uploader_examples.rb +0 -1
  146. data/lib/alchemy/upgrader/seven_point_three.rb +52 -0
  147. data/lib/alchemy/version.rb +1 -1
  148. data/lib/alchemy_cms.rb +1 -1
  149. data/lib/generators/alchemy/install/files/article.css +25 -0
  150. data/lib/generators/alchemy/install/files/custom.css +4 -0
  151. data/lib/generators/alchemy/install/install_generator.rb +6 -6
  152. data/lib/tasks/alchemy/upgrade.rake +29 -1
  153. data/vendor/assets/stylesheets/alchemy_admin/select2.css +1 -0
  154. data/vendor/assets/stylesheets/jquery.Jcrop.min.css +2 -0
  155. data/vendor/javascript/shoelace.min.js +62 -63
  156. data/vendor/javascript/tinymce.min.js +1 -1
  157. metadata +132 -105
  158. data/app/assets/images/alchemy/lupe.cur +0 -0
  159. data/app/assets/stylesheets/alchemy/labels.scss +0 -3
  160. data/app/assets/stylesheets/alchemy/tags.scss +0 -155
  161. data/app/assets/stylesheets/alchemy/welcome.sass +0 -49
  162. data/app/views/alchemy/admin/attachments/_attachment.html.erb +0 -81
  163. data/app/views/alchemy/admin/languages/_language.html.erb +0 -50
  164. data/app/views/alchemy/admin/pages/_table_row.html.erb +0 -111
  165. data/app/views/alchemy/admin/pages/list/_table.html.erb +0 -31
  166. data/app/views/alchemy/admin/pictures/update.js.erb +0 -6
  167. data/app/views/alchemy/admin/tags/_tag.html.erb +0 -32
  168. data/app/views/alchemy/base/update.js.erb +0 -5
  169. data/lib/generators/alchemy/install/files/all.css +0 -11
  170. data/lib/generators/alchemy/install/files/article.scss +0 -30
  171. data/package.json +0 -52
  172. data/vendor/assets/stylesheets/alchemy_admin/select2.scss +0 -741
  173. data/vendor/assets/stylesheets/jquery.Jcrop.min.scss +0 -2
  174. /data/app/assets/stylesheets/alchemy/{fonts.scss → _fonts.scss} +0 -0
  175. /data/app/assets/stylesheets/alchemy/{hints.scss → admin/hints.scss} +0 -0
  176. /data/app/assets/stylesheets/alchemy/{icons.scss → admin/icons.scss} +0 -0
  177. /data/app/assets/stylesheets/alchemy/{images.scss → admin/images.scss} +0 -0
  178. /data/app/assets/stylesheets/alchemy/{preview_window.scss → admin/preview_window.scss} +0 -0
  179. /data/app/assets/stylesheets/alchemy/{spinner.scss → admin/spinner.scss} +0 -0
  180. /data/app/views/alchemy/admin/dashboard/{_locked_pages.html.erb → widgets/_locked_pages.html.erb} +0 -0
  181. /data/app/views/alchemy/admin/dashboard/{_recent_pages.html.erb → widgets/_recent_pages.html.erb} +0 -0
  182. /data/app/views/alchemy/admin/dashboard/{_sites.html.erb → widgets/_sites.html.erb} +0 -0
  183. /data/app/views/alchemy/admin/dashboard/{_users.html.erb → widgets/_users.html.erb} +0 -0
@@ -95,79 +95,6 @@ module Alchemy
95
95
  value_for(role).present?
96
96
  end
97
97
 
98
- # Ingredient validation error messages
99
- #
100
- # == Error messages are translated via I18n
101
- #
102
- # Inside your translation file add translations like:
103
- #
104
- # alchemy:
105
- # ingredient_validations:
106
- # name_of_the_element:
107
- # role_of_the_ingredient:
108
- # validation_error_type: Error Message
109
- #
110
- # NOTE: +validation_error_type+ has to be one of:
111
- #
112
- # * blank
113
- # * taken
114
- # * invalid
115
- #
116
- # === Example:
117
- #
118
- # de:
119
- # alchemy:
120
- # ingredient_validations:
121
- # contactform:
122
- # email:
123
- # invalid: 'Die Email hat nicht das richtige Format'
124
- #
125
- #
126
- # == Error message translation fallbacks
127
- #
128
- # In order to not translate every single ingredient for every element
129
- # you can provide default error messages per ingredient role:
130
- #
131
- # === Example
132
- #
133
- # en:
134
- # alchemy:
135
- # ingredient_validations:
136
- # fields:
137
- # email:
138
- # invalid: E-Mail has wrong format
139
- # blank: E-Mail can't be blank
140
- #
141
- # And even further you can provide general field agnostic error messages:
142
- #
143
- # === Example
144
- #
145
- # en:
146
- # alchemy:
147
- # ingredient_validations:
148
- # errors:
149
- # invalid: %{field} has wrong format
150
- # blank: %{field} can't be blank
151
- #
152
- def ingredient_error_messages
153
- messages = []
154
- ingredients_with_errors.map { |i| [i.role, i.errors.details] }.each do |role, error_details|
155
- error_details[:value].each do |error_detail|
156
- error = error_detail[:error]
157
- messages << Alchemy.t(
158
- "#{name}.#{role}.#{error}",
159
- scope: "ingredient_validations",
160
- default: [
161
- :"fields.#{role}.#{error}",
162
- :"errors.#{error}"
163
- ],
164
- field: Alchemy::Ingredient.translated_label_for(role, name)
165
- )
166
- end
167
- end
168
- messages
169
- end
170
-
171
98
  private
172
99
 
173
100
  # Builds ingredients for this element as described in the +elements.yml+
@@ -79,8 +79,11 @@ module Alchemy
79
79
  end
80
80
 
81
81
  # Returns a dom id used for elements html id tag.
82
- #
82
+ # @deprecated
83
83
  def dom_id
84
+ if caller.none? { |l| l =~ Regexp.new("alchemy/elements_block_helper.rb:117:in `element_view_for'") }
85
+ Alchemy::Deprecation.warn("dom_id is deprecated and will be removed from Alchemy 8.0. Please pass an id to the element_view_for helper instead.")
86
+ end
84
87
  self.class.dom_id_class.new(self).call
85
88
  end
86
89
 
@@ -136,15 +136,21 @@ module Alchemy
136
136
 
137
137
  # The class responsible for the +dom_id+ of elements.
138
138
  # Defaults to +Alchemy::Element::DomId+.
139
+ # @deprecated
139
140
  def dom_id_class
141
+ if caller.none? { |l| l =~ Regexp.new("alchemy/element/presenters.rb:87:in `dom_id'") }
142
+ Alchemy::Deprecation.warn("dom_id_class is deprecated and will be removed from Alchemy 8.0. Please pass an id to the element_view_for helper instead.")
143
+ end
140
144
  @_dom_id_class || DomId
141
145
  end
142
146
 
143
147
  # Register a custom +DomId+ class responsible for the +dom_id+ of elements.
144
148
  # Defaults to +Alchemy::Element::DomId+.
149
+ # @deprecated
145
150
  def dom_id_class=(klass)
146
151
  @_dom_id_class = klass
147
152
  end
153
+ deprecate :dom_id_class=, deprecator: Alchemy::Deprecation
148
154
 
149
155
  # This methods does a copy of source and all its ingredients.
150
156
  #
@@ -115,8 +115,8 @@ module Alchemy
115
115
  self.class.new(select { |e| e.parent_element_id == parent.id })
116
116
  end
117
117
 
118
- def each(&blk)
119
- elements.each(&blk)
118
+ def each(&)
119
+ elements.each(&)
120
120
  end
121
121
 
122
122
  private
@@ -86,6 +86,16 @@ module Alchemy
86
86
  end
87
87
  end
88
88
 
89
+ def validate_length(opts = {})
90
+ value_length = ingredient.value.to_s.length
91
+ if value_length < opts[:minimum]
92
+ ingredient.errors.add(:value, :too_short, count: opts[:minimum])
93
+ end
94
+ if value_length > opts[:maximum]
95
+ ingredient.errors.add(:value, :too_long, count: opts[:maximum])
96
+ end
97
+ end
98
+
89
99
  def duplicates
90
100
  ingredient.class
91
101
  .joins(:element).merge(Alchemy::Element.published)
@@ -124,7 +124,7 @@ module Alchemy
124
124
  end
125
125
 
126
126
  def ransackable_scopes(_auth_object)
127
- [:published, :from_current_site, :searchables, :layoutpages]
127
+ [:published, :contentpages, :from_current_site, :searchables, :layoutpages]
128
128
  end
129
129
  end
130
130
  end
@@ -224,16 +224,6 @@ module Alchemy
224
224
  save!
225
225
  end
226
226
 
227
- # Returns a Hash suitable for jquery fileupload json.
228
- #
229
- def to_jq_upload
230
- {
231
- name: image_file_name,
232
- size: image_file_size,
233
- error: errors[:image_file].join
234
- }
235
- end
236
-
237
227
  # Returns the picture description for a given language.
238
228
  def description_for(language)
239
229
  descriptions.find_by(language: language)&.text
@@ -7,22 +7,80 @@
7
7
  <% end %>
8
8
  <% end %>
9
9
  <% else %>
10
- <table id="all_files" class="list">
11
- <thead>
12
- <tr>
13
- <th class="icon"></th>
14
- <th class="name"><%= sort_link(@query, :name) %></th>
15
- <th class="file_name"><%= sort_link(@query, :file_name) %></th>
16
- <th class="file_type"><%= Alchemy::Attachment.human_attribute_name('file_mime_type') %></th>
17
- <th class="file_size"><%= sort_link(@query, :file_size) %></th>
18
- <th class="date"><%= sort_link(@query, :created_at, default_order: 'desc') %></th>
19
- <th class="tools"></th>
20
- </tr>
21
- </thead>
22
- <tbody>
23
- <%= render partial: 'alchemy/admin/attachments/attachment', collection: @attachments %>
24
- </tbody>
25
- </table>
10
+ <%= render Alchemy::Admin::Resource::Table.new(@attachments, query: @query) do |table| %>
11
+ <% table.icon_column { |attachment| attachment.icon_css_class } %>
12
+ <% table.column :name, sortable: true do |attachment| %>
13
+ <% if can?(:show, attachment) %>
14
+ <%= link_to_dialog(
15
+ attachment.name,
16
+ alchemy.admin_attachment_path(attachment),
17
+ {
18
+ title: attachment.name,
19
+ size: attachment_preview_size(attachment)
20
+ },
21
+ {
22
+ title: Alchemy.t('Attachment Preview')
23
+ }
24
+ ) %>
25
+ <% else %>
26
+ <%= attachment.name %>
27
+ <% end %>
28
+ <% end %>
29
+ <% table.column :file_name, sortable: true %>
30
+ <% table.column :file_mime_type do |attachment| %>
31
+ <%= mime_to_human(attachment.file_mime_type) %>
32
+ <% end %>
33
+ <% table.column :file_size, sortable: true do |attachment| %>
34
+ <%= number_to_human_size(attachment.file_size) %>
35
+ <% end %>
36
+ <% table.column :created_at, sortable: true %>
37
+
38
+ <% table.with_action(:show, Alchemy.t('Attachment Preview')) do |attachment| %>
39
+ <%= link_to_dialog(
40
+ render_icon(:information),
41
+ alchemy.admin_attachment_path(attachment),
42
+ {
43
+ title: attachment.name,
44
+ size: attachment_preview_size(attachment)
45
+ },
46
+ class: "icon_button"
47
+ ) %>
48
+ <% end %>
49
+ <% table.with_action(:download) do |attachment| %>
50
+ <sl-tooltip content="<%= Alchemy.t("download_file", filename: attachment.file_name) %>">
51
+ <%= link_to render_icon(:download),
52
+ alchemy.download_admin_attachment_path(attachment),
53
+ target: "_blank",
54
+ class: "icon_button" %>
55
+ </sl-tooltip>
56
+ <% end %>
57
+ <% table.with_action(:edit, Alchemy.t(:replace_file)) do |attachment| %>
58
+ <%= render 'alchemy/admin/attachments/replace_button',
59
+ redirect_url: alchemy.admin_attachments_path,
60
+ object: attachment,
61
+ file_attribute: 'file' %>
62
+ <% end %>
63
+ <% table.with_action(:destroy, Alchemy.t(:delete_file)) do |attachment| %>
64
+ <%= link_to_confirm_dialog render_icon(:minus),
65
+ Alchemy.t(:confirm_to_delete_file),
66
+ alchemy.admin_attachment_path(
67
+ id: attachment,
68
+ q: search_filter_params[:q],
69
+ page: params[:page],
70
+ per_page: params[:per_page]
71
+ ),
72
+ class: "icon_button" %>
73
+ <% end %>
74
+ <% table.with_action(:edit, Alchemy.t(:rename_file)) do |attachment| %>
75
+ <%= link_to_dialog render_icon(:edit),
76
+ alchemy.edit_admin_attachment_path(attachment, q: search_filter_params[:q], page: params[:page]),
77
+ {
78
+ title: Alchemy.t(:rename_file),
79
+ size: '500x250'
80
+ },
81
+ class: "icon_button" %>
82
+ <% end %>
83
+ <% end %>
26
84
 
27
85
  <%= paginate @attachments, theme: 'alchemy' %>
28
86
  <% end %>
@@ -1,34 +1,39 @@
1
- <%- if @clipboard_items.blank? -%>
2
- <%= render_message do %>
3
- <%= Alchemy.t('No items in your clipboard') %>
4
- <% end %>
5
- <%- else -%>
6
- <div id="clipboard_items">
7
- <ul>
8
- <%- @clipboard_items.each do |item| -%>
9
- <% item_class = item.class.name.demodulize.underscore.pluralize %>
10
- <li id="clipboard_item_<%= item.id -%>" class="<%= item_class -%>">
11
- <% if item_class == 'pages' %>
12
- <%= render_icon(:file) %>
13
- <%= truncate(item.name, length: 50) %>
14
- <% else %>
15
- <%= render_icon(:draggable, style: false) %>
16
- <%= truncate(item.display_name_with_preview_text(50), length: 50) %>
1
+ <% if @clipboard_items.blank? %>
2
+ <%= render_message do %>
3
+ <%= Alchemy.t('No items in your clipboard') %>
4
+ <% end %>
5
+ <% else %>
6
+ <%= render_message do %>
7
+ <%= Alchemy.t('Add items from clipboard via "Add Element" button') %>
8
+ <% end %>
9
+
10
+ <div id="clipboard_items">
11
+ <ul>
12
+ <% @clipboard_items.each do |item| %>
13
+ <% item_class = item.class.name.demodulize.underscore.pluralize %>
14
+ <li id="clipboard_item_<%= item.id %>" class="<%= item_class %>">
15
+ <% if item_class == 'pages' %>
16
+ <%= render_icon(:file) %>
17
+ <%= truncate(item.name, length: 50) %>
18
+ <% else %>
19
+ <%= render_icon(:draggable, style: false) %>
20
+ <%= truncate(item.display_name_with_preview_text(50), length: 50) %>
21
+ <% end %>
22
+ <sl-tooltip content="<%= Alchemy.t('Remove item from clipboard') %>">
23
+ <%= link_to render_icon(:close, size: '1x'),
24
+ alchemy.remove_admin_clipboard_path(remarkable_type: item_class, remarkable_id: item.id),
25
+ remote: true, method: 'delete',
26
+ class: "icon_button small"
27
+ %>
28
+ </sl-tooltip>
29
+ </li>
17
30
  <% end %>
18
- <span class="float_right">
19
- <%= link_to render_icon(:close, size: '1x'),
20
- alchemy.remove_admin_clipboard_path(remarkable_type: item_class, remarkable_id: item.id),
21
- remote: true, method: 'delete',
22
- title: Alchemy.t('Remove item from clipboard') %>
23
- </span>
24
- </li>
25
- <%- end -%>
26
- </ul>
27
- <p>
28
- <%= link_to_confirm_dialog Alchemy.t('clear clipboard'),
29
- Alchemy.t('Do you really want to clear the clipboard?'),
30
- alchemy.clear_admin_clipboard_path(remarkable_type: params[:remarkable_type]),
31
- class: 'button' %>
32
- </p>
33
- </div>
34
- <%- end -%>
31
+ </ul>
32
+ <p>
33
+ <%= link_to_confirm_dialog Alchemy.t('clear clipboard'),
34
+ Alchemy.t('Do you really want to clear the clipboard?'),
35
+ alchemy.clear_admin_clipboard_path(remarkable_type: params[:remarkable_type]),
36
+ class: 'button' %>
37
+ </p>
38
+ </div>
39
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <%= render "top" %>
2
+ <%= render "left_column" %>
3
+ <%= render "right_column" %>
@@ -0,0 +1,4 @@
1
+ <div class="column left">
2
+ <%= render 'alchemy/admin/dashboard/widgets/locked_pages' %>
3
+ <%= render 'alchemy/admin/dashboard/widgets/recent_pages' %>
4
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="column right">
2
+ <% if @online_users.try(:any?) %>
3
+ <%= render 'alchemy/admin/dashboard/widgets/users' %>
4
+ <% end %>
5
+
6
+ <% if multi_site? %>
7
+ <%= render 'alchemy/admin/dashboard/widgets/sites' %>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,12 @@
1
+ <h1>
2
+ <% if @first_time -%>
3
+ <%= Alchemy.t(:welcome_note, name: current_alchemy_user.try(:name)) %>
4
+ <% else -%>
5
+ <%= Alchemy.t(:welcome_back_note, name: current_alchemy_user.try(:name)) %>
6
+ <% end -%>
7
+ </h1>
8
+ <% if @last_sign_at %>
9
+ <p>
10
+ <small><%= Alchemy.t('Your last login was on', time: l(@last_sign_at, format: :'alchemy.default')) %></small>
11
+ </p>
12
+ <% end %>
@@ -16,29 +16,5 @@
16
16
  <% end %>
17
17
 
18
18
  <div id="dashboard">
19
- <h1>
20
- <% if @first_time -%>
21
- <%= Alchemy.t(:welcome_note, name: current_alchemy_user.try(:name)) %>
22
- <% else -%>
23
- <%= Alchemy.t(:welcome_back_note, name: current_alchemy_user.try(:name)) %>
24
- <% end -%>
25
- </h1>
26
- <% if @last_sign_at %>
27
- <p>
28
- <small><%= Alchemy.t('Your last login was on', time: l(@last_sign_at, format: :'alchemy.default')) %></small>
29
- </p>
30
- <% end %>
31
- <div class="column left">
32
- <%= render 'locked_pages' %>
33
- <%= render 'recent_pages' %>
34
- </div>
35
- <div class="column right">
36
- <% if @online_users.try(:any?) %>
37
- <%= render 'users' %>
38
- <% end %>
39
-
40
- <% if multi_site? %>
41
- <%= render 'sites' %>
42
- <% end %>
43
- </div>
19
+ <%= render "dashboard" %>
44
20
  </div>
@@ -29,9 +29,8 @@
29
29
  html: {id: "element_#{element.id}_form".html_safe, class: 'element-body'} do |f| %>
30
30
 
31
31
  <div id="element_<%= element.id %>_errors" class="element_errors hidden">
32
- <h2><%= Alchemy.t("Validation failed") %></h2>
32
+ <alchemy-icon name="alert"></alchemy-icon>
33
33
  <p><%= Alchemy.t(:ingredient_validations_headline) %></p>
34
- <ul class="error-messages"></ul>
35
34
  </div>
36
35
 
37
36
  <!-- Ingredients -->
@@ -10,7 +10,7 @@
10
10
  collection: elements_for_select(@elements),
11
11
  prompt: Alchemy.t(:select_element),
12
12
  selected: (@elements.first if @elements.count == 1),
13
- input_html: {is: 'alchemy-select', autofocus: true, disabled: @elements.count == 1} %>
13
+ input_html: {is: 'alchemy-select', autofocus: true} %>
14
14
  <% if @elements.count == 1 %>
15
15
  <%= form.hidden_field :name, value: @elements.first[:name] %>
16
16
  <% end %>
@@ -9,9 +9,16 @@
9
9
  include_blank: false %>
10
10
  <%- end -%>
11
11
  <%- if ingredient.settings[:css_classes].present? -%>
12
- <%= f.input :css_class,
13
- collection: ingredient.settings[:css_classes],
14
- include_blank: Alchemy.t('None') %>
12
+ <% css_classes = ingredient.settings[:css_classes] %>
13
+ <% css_classes_collection = case css_classes.first
14
+ when Array
15
+ then css_classes
16
+ else
17
+ css_classes.map do |klass|
18
+ [Alchemy.t(klass, scope: "picture_ingredients.css_classes", default: picture_editor.css_class.camelcase), klass]
19
+ end
20
+ end %>
21
+ <%= f.input :css_class, collection: css_classes_collection, include_blank: false %>
15
22
  <%- else -%>
16
23
  <% Alchemy::Deprecation.warn %(Float positioning in Picture ingredients is deprecated. If you rely on them, please use `css_classes` in your "#{ingredient.role}" settings instead.) %>
17
24
  <%= f.input :css_class,
@@ -3,3 +3,10 @@
3
3
  <% if @ingredient.settings[:anchor] %>
4
4
  <alchemy-action name="updateAnchorIcon" params="<%= [@ingredient.id, @ingredient.dom_id.present?].to_json %>"></alchemy-action>
5
5
  <% end %>
6
+ <% if @ingredient.type == "Alchemy::Ingredients::Picture" && @ingredient.css_class.present? %>
7
+ <%= turbo_stream.replace_all "[data-ingredient-id='#{@ingredient.id}'] .picture_ingredient_css_class",
8
+ partial: "alchemy/ingredients/shared/picture_css_class",
9
+ locals: {
10
+ css_class: Alchemy::IngredientEditor.new(@ingredient).css_class
11
+ } %>
12
+ <% end %>
@@ -1,44 +1,18 @@
1
- <%- if @languages.any? -%>
2
- <table class="list" id="languages_list">
3
- <thead>
4
- <tr>
5
- <th class="icon"></th>
6
- <th>
7
- <%= sort_link @query, :name %>
8
- </th>
9
- <th>
10
- <%= sort_link @query, :language_code %>
11
- </th>
12
- <th>
13
- <%= sort_link @query, :country_code %>
14
- </th>
15
- <th>
16
- <%= Alchemy::Language.human_attribute_name(:code) %>
17
- </th>
18
- <th>
19
- <%= Alchemy::Language.human_attribute_name(:locale) %>
20
- </th>
21
- <th>
22
- <%= Alchemy::Language.human_attribute_name(:frontpage_name) %>
23
- </th>
24
- <th>
25
- <%= Alchemy::Language.human_attribute_name(:page_layout) %>
26
- </th>
27
- <th class="center">
28
- <%= Alchemy::Language.human_attribute_name(:public) %>
29
- </th>
30
- <th class="center">
31
- <%= Alchemy::Language.human_attribute_name(:default) %>
32
- </th>
33
- <th class="tools"></th>
34
- </tr>
35
- </thead>
36
- <tbody>
37
- <%= render_resources %>
38
- </tbody>
39
- </table>
40
- <%- elsif search_filter_params[:q].present? -%>
41
- <p><%= Alchemy.t('Nothing found') %></p>
42
- <%- end -%>
1
+ <%= render Alchemy::Admin::Resource::Table.new(@languages, query: @query, search_filter_params: search_filter_params) do |table| %>
2
+ <% table.icon_column "translate-2", style: false %>
3
+ <% table.column :name, sortable: true %>
4
+ <% table.column :language_code, sortable: true %>
5
+ <% table.column :country_code %>
6
+ <% table.column :code %>
7
+ <% table.column :locale %>
8
+ <% table.column :frontpage_name %>
9
+ <% table.column :page_layout do |row| %>
10
+ <%= Alchemy::Page.human_layout_name(row.page_layout) %>
11
+ <% end %>
12
+ <% table.column :public %>
13
+ <% table.column :default %>
14
+ <% table.delete_button tooltip: Alchemy.t(:delete_language) %>
15
+ <% table.edit_button tooltip: Alchemy.t(:edit_language), dialog_size: "430x415" %>
16
+ <% end %>
43
17
 
44
18
  <%= paginate @languages, theme: 'alchemy' %>
@@ -13,7 +13,7 @@
13
13
  value: node.page && node.read_attribute(:name).blank? ? nil : node.name,
14
14
  placeholder: node.page ? node.page.name : nil
15
15
  } %>
16
- <%= render Alchemy::Admin::PageSelect.new(node.page, allow_clear: true) do %>
16
+ <%= render Alchemy::Admin::PageSelect.new(node.page, allow_clear: true, query_params: {contentpages: true}) do %>
17
17
  <%= f.input :page_id, label: Alchemy::Page.model_name.human %>
18
18
  <% end %>
19
19
  <%= f.input :url, input_html: { disabled: node.page }, hint: Alchemy.t(:node_url_hint) %>