alchemy_cms 8.0.0.b → 8.0.0.c

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/alchemy/admin.css +1 -1
  3. data/app/assets/images/alchemy/element_icons/layout-bottom-2-line.svg +1 -0
  4. data/app/components/alchemy/admin/link_dialog/tabs.rb +1 -1
  5. data/app/components/alchemy/admin/locale_select.rb +38 -0
  6. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  7. data/app/controllers/alchemy/admin/pictures_controller.rb +11 -5
  8. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  9. data/app/decorators/alchemy/ingredient_editor.rb +9 -1
  10. data/app/helpers/alchemy/admin/base_helper.rb +0 -7
  11. data/app/helpers/alchemy/admin/form_helper.rb +2 -1
  12. data/app/models/alchemy/element_definition.rb +3 -2
  13. data/app/models/alchemy/ingredients/boolean.rb +2 -1
  14. data/app/models/alchemy/page/publisher.rb +1 -1
  15. data/app/models/alchemy/resource.rb +15 -2
  16. data/app/models/alchemy/storage_adapter/dragonfly.rb +2 -2
  17. data/app/stylesheets/alchemy/admin/dashboard.scss +13 -0
  18. data/app/stylesheets/alchemy/admin/elements.scss +1 -1
  19. data/app/stylesheets/alchemy/admin/nodes.scss +6 -2
  20. data/app/stylesheets/alchemy/admin/sitemap.scss +6 -17
  21. data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
  22. data/app/views/alchemy/admin/dashboard/info.html.erb +36 -6
  23. data/app/views/alchemy/admin/elements/_header.html.erb +8 -9
  24. data/app/views/alchemy/admin/nodes/_form.html.erb +5 -1
  25. data/app/views/alchemy/admin/pictures/_archive.html.erb +1 -1
  26. data/app/views/alchemy/admin/pictures/_form.html.erb +10 -5
  27. data/app/views/alchemy/admin/pictures/_picture.html.erb +15 -10
  28. data/app/views/alchemy/admin/pictures/show.html.erb +11 -13
  29. data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +1 -1
  30. data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
  31. data/app/views/layouts/alchemy/admin.html.erb +3 -6
  32. data/lib/alchemy/configuration/base_option.rb +18 -5
  33. data/lib/alchemy/configuration/boolean_option.rb +2 -5
  34. data/lib/alchemy/configuration/collection_option.rb +69 -0
  35. data/lib/alchemy/configuration/configuration_option.rb +35 -0
  36. data/lib/alchemy/configuration/pathname_option.rb +12 -0
  37. data/lib/alchemy/configuration.rb +44 -6
  38. data/lib/alchemy/configurations/importmap.rb +11 -0
  39. data/lib/alchemy/configurations/mailer.rb +2 -2
  40. data/lib/alchemy/configurations/main.rb +141 -3
  41. data/lib/alchemy/configurations/uploader.rb +2 -2
  42. data/lib/alchemy/deprecation.rb +1 -1
  43. data/lib/alchemy/engine.rb +27 -14
  44. data/lib/alchemy/test_support/config_stubbing.rb +13 -4
  45. data/lib/alchemy/test_support/factories/language_factory.rb +8 -4
  46. data/lib/alchemy/test_support/factories/page_factory.rb +1 -0
  47. data/lib/alchemy/version.rb +1 -1
  48. data/lib/alchemy.rb +16 -160
  49. data/lib/generators/alchemy/install/templates/alchemy.rb.tt +78 -7
  50. data/lib/tasks/alchemy/assets.rake +1 -1
  51. metadata +7 -6
  52. data/app/assets/images/alchemy/element_icons/default.svg +0 -1
  53. data/lib/alchemy/configuration/class_set_option.rb +0 -46
  54. data/lib/alchemy/configuration/integer_list_option.rb +0 -13
  55. data/lib/alchemy/configuration/list_option.rb +0 -22
  56. data/lib/alchemy/configuration/string_list_option.rb +0 -13
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21 3C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H21ZM20 5H4V19H20V5ZM18 15V17H6V15H18Z"></path></svg>
@@ -25,7 +25,7 @@ module Alchemy
25
25
  end
26
26
 
27
27
  def tabs
28
- Alchemy.link_dialog_tabs
28
+ Alchemy.config.link_dialog_tabs
29
29
  end
30
30
  end
31
31
  end
@@ -0,0 +1,38 @@
1
+ module Alchemy
2
+ module Admin
3
+ # Renders a locale select tag for switching the backend locale.
4
+ class LocaleSelect < ViewComponent::Base
5
+ attr_reader :name
6
+
7
+ def initialize(name = :change_locale)
8
+ @name = name
9
+ end
10
+
11
+ def call
12
+ select_tag(
13
+ name,
14
+ options_for_select(
15
+ translations_for_select,
16
+ ::I18n.locale
17
+ )
18
+ )
19
+ end
20
+
21
+ def render?
22
+ available_locales.many?
23
+ end
24
+
25
+ private
26
+
27
+ def available_locales
28
+ @_available_locales ||= Alchemy::I18n.available_locales.sort!
29
+ end
30
+
31
+ def translations_for_select
32
+ available_locales.map do |locale|
33
+ [Alchemy.t(locale, scope: :translations), locale]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -114,7 +114,7 @@ module Alchemy
114
114
  elsif page_needs_lock?
115
115
  @page.lock_to!(current_alchemy_user)
116
116
  end
117
- @preview_urls = Alchemy.preview_sources.map do |klass|
117
+ @preview_urls = Alchemy.config.preview_sources.map do |klass|
118
118
  [
119
119
  klass.model_name.human,
120
120
  klass.new(routes: Alchemy::Engine.routes).url_for(@page)
@@ -29,8 +29,10 @@ module Alchemy
29
29
  add_alchemy_filter :without_tag, type: :checkbox
30
30
  add_alchemy_filter :deletable, type: :checkbox
31
31
 
32
+ helper_method :picture_offset
33
+
32
34
  def index
33
- @pictures = filtered_pictures
35
+ @pictures = filtered_pictures(page: params[:page])
34
36
 
35
37
  if in_overlay?
36
38
  archive_overlay
@@ -38,7 +40,7 @@ module Alchemy
38
40
  end
39
41
 
40
42
  def show
41
- @pictures = filtered_pictures(per_page: 1)
43
+ @pictures = filtered_pictures(page: params[:picture_index], per_page: 1)
42
44
  @picture = @pictures.first
43
45
  @previous = @pictures.prev_page
44
46
  @next = @pictures.next_page
@@ -121,7 +123,7 @@ module Alchemy
121
123
  redirect_to_index
122
124
  end
123
125
 
124
- def filtered_pictures(per_page: items_per_page)
126
+ def filtered_pictures(page: 1, per_page: items_per_page)
125
127
  @query = Picture.ransack(search_filter_params[:q])
126
128
  @query.sorts = default_sort_order if @query.sorts.empty?
127
129
  pictures = @query.result
@@ -130,7 +132,7 @@ module Alchemy
130
132
  pictures = pictures.tagged_with(params[:tagged_with])
131
133
  end
132
134
 
133
- pictures = pictures.page(params[:page] || 1).per(per_page)
135
+ pictures = pictures.page(page).per(per_page)
134
136
  Alchemy.storage_adapter.preloaded_pictures(pictures)
135
137
  end
136
138
 
@@ -150,7 +152,7 @@ module Alchemy
150
152
  cookies[:alchemy_pictures_per_page] = params[:per_page] ||
151
153
  cookies[:alchemy_pictures_per_page] ||
152
154
  pictures_per_page_for_size
153
- end
155
+ end.to_i
154
156
  end
155
157
 
156
158
  def items_per_page_options
@@ -160,6 +162,10 @@ module Alchemy
160
162
 
161
163
  private
162
164
 
165
+ def picture_offset
166
+ ((params[:page] || 1).to_i - 1) * items_per_page
167
+ end
168
+
163
169
  def set_size
164
170
  @size = params[:size] || session[:alchemy_pictures_size] || "medium"
165
171
  session[:alchemy_pictures_size] = @size
@@ -128,7 +128,7 @@ module Alchemy
128
128
  # @see Alchemy::Resource#editable_attributes
129
129
  def resource_params
130
130
  params.require(resource_handler.namespaced_resource_name).permit(
131
- resource_handler.editable_attributes.map { _1[:name] }
131
+ resource_handler.permitted_attributes
132
132
  )
133
133
  end
134
134
 
@@ -108,7 +108,15 @@ module Alchemy
108
108
  end
109
109
 
110
110
  def format_validation
111
- validations.select { _1.is_a?(Hash) }.find { _1[:format] }&.fetch(:format)
111
+ format = validations.select { _1.is_a?(Hash) }.find { _1[:format] }&.fetch(:format)
112
+ return nil unless format
113
+
114
+ # If format is a string or symbol, resolve it from config format_matchers
115
+ if format.is_a?(String) || format.is_a?(Symbol)
116
+ Alchemy.config.format_matchers.get(format)
117
+ else
118
+ format
119
+ end
112
120
  end
113
121
 
114
122
  def length_validation
@@ -66,13 +66,6 @@ module Alchemy
66
66
  end
67
67
  end
68
68
 
69
- # Used for translations selector in Alchemy cockpit user settings.
70
- def translations_for_select
71
- Alchemy::I18n.available_locales.sort.map do |locale|
72
- [Alchemy.t(locale, scope: :translations), locale]
73
- end
74
- end
75
-
76
69
  def alchemy_admin_js_translations(locale = ::I18n.locale)
77
70
  render partial: "alchemy/admin/translations/#{locale}", formats: [:js]
78
71
  rescue ActionView::MissingTemplate
@@ -19,7 +19,8 @@ module Alchemy
19
19
  options.key?(:remote) || options[:remote] = request.xhr?
20
20
  options[:html] = {
21
21
  id: options.delete(:id),
22
- class: ["alchemy", options.delete(:class)].compact.join(" ")
22
+ class: ["alchemy", options.delete(:class)].compact.join(" "),
23
+ novalidate: false
23
24
  }
24
25
  simple_form_for(object, *(args << options), &block)
25
26
  end
@@ -35,6 +35,8 @@ module Alchemy
35
35
 
36
36
  delegate :blank?, to: :name
37
37
 
38
+ DEFAULT_ICON_NAME = "layout-bottom-2-line"
39
+
38
40
  class << self
39
41
  # Returns the definitions from elements.yml file.
40
42
  #
@@ -168,8 +170,7 @@ module Alchemy
168
170
  case icon
169
171
  when TrueClass then name
170
172
  when String then icon
171
- else
172
- "default"
173
+ else DEFAULT_ICON_NAME
173
174
  end
174
175
  end
175
176
 
@@ -6,7 +6,8 @@ module Alchemy
6
6
  #
7
7
  class Boolean < Alchemy::Ingredient
8
8
  def value
9
- ActiveRecord::Type::Boolean.new.cast(self[:value])
9
+ val = self[:value].nil? ? definition.default : self[:value]
10
+ ActiveRecord::Type::Boolean.new.cast(val)
10
11
  end
11
12
 
12
13
  # The localized value
@@ -40,7 +40,7 @@ module Alchemy
40
40
  end
41
41
  end
42
42
 
43
- Alchemy.publish_targets.each { |p| p.perform_later(page) }
43
+ Alchemy.config.publish_targets.each { |p| p.perform_later(page) }
44
44
  end
45
45
 
46
46
  private
@@ -152,7 +152,7 @@ module Alchemy
152
152
  end
153
153
 
154
154
  def attributes
155
- @_attributes ||= model.columns.collect do |col|
155
+ @_attributes ||= model.columns.filter_map do |col|
156
156
  next if skipped_attributes.include?(col.name)
157
157
 
158
158
  {
@@ -161,7 +161,7 @@ module Alchemy
161
161
  relation: resource_relation(col.name),
162
162
  enum: enum_values_collection_for_select(col.name)
163
163
  }.delete_if { |_k, v| v.blank? }
164
- end.compact
164
+ end
165
165
  end
166
166
 
167
167
  def enum_values_collection_for_select(column_name)
@@ -199,6 +199,19 @@ module Alchemy
199
199
  attributes.reject { |h| restricted_attributes.map(&:to_s).include?(h[:name].to_s) }
200
200
  end
201
201
 
202
+ # Returns a list of attribute names that are permitted to be updated.
203
+ # Uses {editable_attributes} and adds {tag_list} if model is taggable.
204
+ # Used in strong parameters of Alchemy::Admin::ResourcesController.
205
+ #
206
+ # @return [Array<String>]
207
+ def permitted_attributes
208
+ attrs = editable_attributes.map { _1[:name] }
209
+ if model < Alchemy::Taggable
210
+ attrs << "tag_list"
211
+ end
212
+ attrs
213
+ end
214
+
202
215
  # Returns all attribute names that are searchable in the admin interface
203
216
  #
204
217
  def searchable_attribute_names
@@ -15,7 +15,7 @@ module Alchemy
15
15
 
16
16
  has_many :thumbs, class_name: "Alchemy::PictureThumb", dependent: :destroy
17
17
 
18
- before_save do
18
+ before_save if: :image_file_name do
19
19
  self.image_file_name = sanitized_filename(image_file_name)
20
20
  end
21
21
 
@@ -35,7 +35,7 @@ module Alchemy
35
35
  }
36
36
  end
37
37
 
38
- before_save do
38
+ before_save if: :file_name do
39
39
  self.file_name = sanitized_filename(file_name)
40
40
  end
41
41
  end
@@ -47,6 +47,19 @@
47
47
  }
48
48
  }
49
49
 
50
+ .logo {
51
+ display: flex;
52
+ flex-direction: column;
53
+ justify-content: center;
54
+ align-items: center;
55
+ margin-bottom: 0.5em;
56
+
57
+ svg {
58
+ width: 200px;
59
+ height: auto;
60
+ }
61
+ }
62
+
50
63
  alchemy-update-check {
51
64
  display: flex;
52
65
  position: relative;
@@ -119,7 +119,7 @@ alchemy-tinymce {
119
119
  flex-grow: 1;
120
120
  white-space: nowrap;
121
121
  transition: color var(--transition-duration);
122
- line-height: 1;
122
+ line-height: 1.5;
123
123
  max-width: 85%;
124
124
 
125
125
  .preview_text_quote {
@@ -97,8 +97,12 @@
97
97
  background-color: var(--sitemap-highlight-color);
98
98
  }
99
99
 
100
- &.no-match .sitemap_pagename_link {
101
- color: var(--color-grey_light);
100
+ &.no-match {
101
+ .nodes_tree-right_tools,
102
+ .node_name,
103
+ .node_url {
104
+ opacity: 0.25;
105
+ }
102
106
  }
103
107
 
104
108
  &:hover {
@@ -118,8 +118,12 @@
118
118
  background-color: var(--sitemap-highlight-color);
119
119
  }
120
120
 
121
- &.no-match .sitemap_pagename_link {
122
- color: var(--color-grey_light);
121
+ &.no-match {
122
+ .sitemap_right_tools,
123
+ .sitemap_sitename,
124
+ .sitemap_url {
125
+ opacity: 0.25;
126
+ }
123
127
  }
124
128
 
125
129
  &:hover {
@@ -252,21 +256,6 @@
252
256
  margin-left: var(--spacing-2);
253
257
  }
254
258
 
255
- .alchemy-dialog {
256
- #sitemap-wrapper {
257
- min-height: 0;
258
- }
259
-
260
- #sitemap {
261
- margin: 0;
262
- padding: 0 var(--spacing-6) var(--spacing-2) var(--spacing-2);
263
-
264
- .page_icon {
265
- cursor: default;
266
- }
267
- }
268
- }
269
-
270
259
  #search_field_clear {
271
260
  cursor: pointer;
272
261
  }
@@ -7,7 +7,7 @@
7
7
  title: Alchemy.t(:info),
8
8
  dialog_options: {
9
9
  title: Alchemy.t(:info),
10
- size: "420x435"
10
+ size: "420x380"
11
11
  },
12
12
  if_permitted_to: [:info, :alchemy_admin_dashboard],
13
13
  hotkey: 'alt+i'
@@ -1,12 +1,42 @@
1
+ <div class="logo">
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 267 91"
5
+ >
6
+ <path
7
+ d="M261.749 29.77h-9.812l-.72 2.738a193.53 193.53 0 0 0-.802 3.217c-.334-1.384-.604-2.5-.767-3.162l-.685-2.792H234.075c-1.102-.371-2.338-.564-3.705-.564-2.537 0-4.557.864-6.104 1.934-1.406-1.15-3.402-1.934-6.221-1.934-1.341 0-2.524.242-3.564.625l-.006-.061H201.334v4.17c-2.345-3.051-5.884-4.735-10.401-4.735-4.196 0-8.831 1.936-11.655 6.784-1.194-3.746-3.896-6.784-9.557-6.784-1.385 0-2.626.24-3.727.617v-12.19l-4.204.623-6.934 1.027-3.132.464v10.324a22.109 22.109 0 0 0-6.086-.864c-5.96 0-9.341 2.652-11.128 4.876-.108.133-.2.284-.303.422V17.633l-4.207.623-6.933 1.027-3.131.464v24.04l-5.118-18.709-.739-2.701H99.863l-.745 2.686L95.854 36.8 80.915 21.597a2.922 2.922 0 0 0-2.823-.776l-18.554 4.875a2.918 2.918 0 0 0-.634-.981L39.437 4.906a2.927 2.927 0 0 0-2.826-.777L9.797 11.173a2.92 2.92 0 0 0-2.073 2.054L.372 40.078a2.922 2.922 0 0 0 .735 2.818L20.6 62.705a2.921 2.921 0 0 0 2.822.774l9.259-2.43-3.051 11.1a2.921 2.921 0 0 0 .735 2.821l10.94 11.122a2.92 2.92 0 0 0 2.822.778l15.08-3.953a2.919 2.919 0 0 0 2.077-2.055l3.536-12.978.316.324a2.928 2.928 0 0 0 2.064.872c.254.001.508-.031.761-.098l20.839-5.48H103.275l.72-2.733.82-3.121h3.794l.822 3.122.718 2.732h24.059v-4.307c.07.092.133.194.207.282 1.729 2.119 5.001 4.643 10.76 4.643 2.735 0 4.945-.705 6.55-1.415v.797H180.119v-4.383c2.392 3.007 5.737 4.495 9.134 4.885-1.602 1.106-3.095 2.759-4.467 4.952-2.161 3.454-3.211 6.441-3.211 9.137 0 2.014.524 3.774 1.562 5.236 1.388 1.967 3.57 3.053 6.143 3.053.226 0 .384-.016.896-.073.142-.014.243-.025.312-.03 1.014-.043 2.078-.446 4.047-1.521.468-.248.973-.622 2.077-1.656.966 3.029 2.97 3.501 4.119 3.501 2.479 0 4.354-1.665 4.575-4.057.007-.045.041-.233.189-.649.774 1.335 2.059 2.415 4.188 2.415 2.658 0 4.791-2.088 6.555-4.378.065.155.132.312.203.47 1.794 4.082 4.646 4.694 6.185 4.694.76 0 1.52-.168 2.307-.503.228.213.463.419.726.605a6.818 6.818 0 0 0 3.993 1.302c2.273 0 4.515-.764 6.661-2.274 3.357-2.369 4.061-5.111 4.061-6.996 0-2.266-1.092-4.215-3.014-5.406a4.177 4.177 0 0 0 2.142-1.312c.918 1.27 1.794 2.475 2.303 3.129l1.917 2.468 2.74-1.503.268-.144c2.382-1.291 7.335-3.979 9.847-12.048l8.677-27.888 1.479-4.759h-4.984z"
8
+ fill="transparent"
9
+ />
10
+ <path
11
+ fill="currentColor"
12
+ d="M102.705 26.102h8.626l9.245 33.793h-7.549l-1.541-5.856h-9.448l-1.541 5.856h-7.189l9.397-33.793zm.411 23.008h7.291c-1.282-5.857-2.925-12.841-3.594-16.487-.719 3.647-2.362 10.63-3.697 16.487zm27.472 10.786h-6.931V22.969l6.931-1.026v37.953zm22.187-1.748c-.977.409-3.545 2.364-7.549 2.364-6.883 0-10.682-4.314-10.682-13.405 0-9.554 3.953-14.176 11.143-14.176 2.878 0 5.239.719 6.163 1.079l-.822 5.083c-.666-.256-2.517-.822-4.365-.822-3.388 0-4.981 2.62-4.981 8.579 0 6.061 1.747 8.267 4.775 8.267 2.108 0 4.008-1.128 4.726-1.386l1.592 4.417zm2.671-35.179l6.931-1.026v14.943h.105c.717-.667 3.079-3.954 7.291-3.954 4.826 0 6.728 2.979 6.728 9.193v17.771h-6.934V43.819c0-3.801-.616-4.879-2.721-4.879-2.107 0-3.853 2.157-4.47 2.876v18.079h-6.931V22.969zm44.73 35.026c-.771.514-3.956 2.518-9.038 2.518-5.957 0-10.785-3.852-10.785-13.097 0-9.811 4.775-14.484 10.63-14.484 5.854 0 9.963 3.646 9.963 12.273 0 1.851-.257 3.339-.309 3.597h-13.401c.05 4.571 2.311 6.469 5.235 6.469 2.773 0 5.086-1.231 6.319-1.795l1.386 4.519zm-12.941-13.509h7.034c0-5.237-1.437-6.624-3.338-6.624-1.798 0-3.646 1.643-3.696 6.624zm17.82-10.989h6.107l.31 3.543c.772-.925 2.722-4.109 6.624-4.109 2.98 0 4.828 1.027 5.598 4.057.874-1.181 3.03-4.057 6.728-4.057 4.468 0 6.37 2.517 6.37 9.141v17.823h-6.883V42.637c0-2.311-.358-3.697-2.158-3.697-1.797 0-3.183 2.054-3.543 2.876v18.079h-6.625V42.637c0-2.311-.358-3.697-2.157-3.697-1.796 0-3.131 2.003-3.542 2.876v18.079h-6.828V33.497zm56.744 0l-8.679 27.887c-2.156 6.934-6.213 8.886-8.37 10.067-.718-.926-2.414-3.287-3.081-4.213.771-.668 4.467-2.566 5.546-6.778l-8.318-26.963h7.239c.771 3.132 3.545 14.688 4.314 19.002.821-4.417 3.545-15.87 4.367-19.002h6.982z"
13
+ />
14
+ <g>
15
+ <path
16
+ fill="currentColor"
17
+ d="M193.986 68.011c.319 0 .667.193 1.031.578.897.95 1.506 1.125 2.353.546.367-.254.548-.633.508-1.05-.054-.799-.66-1.456-1.799-1.957-.818-.364-1.438-.541-1.896-.541-2.436.013-4.74 1.736-6.854 5.116-1.807 2.889-2.722 5.389-2.722 7.435 0 1.336.326 2.474.969 3.379.796 1.128 1.983 1.701 3.526 1.701.029 0 .213-.016.555-.054.268-.028.427-.045.47-.046.306 0 .867-.139 2.703-1.14.226-.117.704-.468 2.439-2.166 1.932-1.896 2.285-2.549 2.366-2.884.084-.275.01-.583-.22-.921-.238-.344-.523-.518-.838-.518a.786.786 0 0 0-.708.429c-.872 1.35-1.932 2.444-3.146 3.266-1.295.868-2.615 1.308-3.923 1.308-.778 0-1.671-.234-1.671-2.074 0-1.427.742-3.47 2.211-6.08 1.621-2.872 3.183-4.327 4.646-4.327zm30.25 10.553c-.354 0-.695.247-1.103.798-.301.408-.535.409-.654.408-.259-.01-1.135-.388-1.441-4.977l-.305-4.414c-.25-1.795-.915-2.704-1.979-2.704-.68 0-1.78.545-4.245 4.804a46.07 46.07 0 0 1-2.457 3.695c-.936 1.256-1.511 1.87-1.856 2.171-.082-.436-.124-.979-.124-1.635 0-.533.027-1.253.081-2.143.055-.995.089-1.633.101-1.925.039-2.004-.251-3.293-.885-3.941a1.569 1.569 0 0 0-1.157-.483c-1.114 0-2.453 1.26-4.214 3.968-.44.683-1.144 1.88-2.093 3.565.149-2.311.529-4.59 1.141-6.795.071-.267.054-.669-.433-1.089-.33-.287-.703-.436-1.107-.436-.863 0-1.277 1.173-1.539 2.19-.313 1.16-.526 2.592-.635 4.245-.119 1.754-.181 3.891-.181 6.36 0 .357.075.868.233 1.577.203.807.5 1.631 1.17 1.631.813 0 1.32-.423 1.381-1.157.113-1.165 1.095-3.422 2.918-6.71 1.54-2.804 2.334-3.953 2.701-4.42 0 .089 0 .194-.005.32-.15 3.265-.211 5.245-.182 5.886.105 2.516.823 3.792 2.139 3.792 1.21 0 2.685-1.261 4.636-3.968.255-.355 2.324-3.588 3.537-5.488.234-.37.414-.648.545-.854.012.086.021.184.031.293.052.55.064 1.329.038 2.328v2.002c.01 1.115.313 2.354.903 3.685.812 1.851 1.907 2.786 3.252 2.786.459 0 .972-.164 1.575-.502.819-.475 1.234-1.083 1.234-1.804.001-.652-.392-1.059-1.021-1.059zm6.628-4.902c-2.19 0-2.468-.365-2.475-.365 0-.874.821-2.04 2.372-3.37 1.809-1.556 2.828-1.882 3.366-1.882.036 0 .073.003.123.006.072.004.298.046.826.328.721.386.872.415 1.009.415.727 0 1.163-.494 1.163-1.324 0-.631-.425-1.187-1.268-1.647-.651-.35-1.201-.517-1.684-.517-1.572 0-3.401 1.039-5.592 3.175-2.195 2.138-3.262 3.892-3.262 5.361 0 .738.509 1.313 1.518 1.711.65.258 1.33.402 2.023.432l3.86.141c.473.023.891.157 1.28.407.556.367.619.737.619.983 0 .86-1.161 1.629-2.133 2.122-1.358.688-2.57 1.035-3.598 1.035-.625 0-.625-.247-.625-.444 0-.104.017-.197.054-.283.126-.3.213-.694.266-1.218l.035-.339-.312-.132c-.656-.279-1.311.032-1.813.841-.316.495-.47.93-.47 1.33 0 .904.4 1.646 1.192 2.199a3.557 3.557 0 0 0 2.134.712c1.598 0 3.218-.569 4.811-1.693 1.794-1.263 2.701-2.733 2.701-4.371.002-2.398-2.057-3.613-6.12-3.613z"
18
+ />
19
+ </g>
20
+ <g fill-rule="evenodd" clip-rule="evenodd" fill="currentColor">
21
+ <path
22
+ d="M47.632 51.588L23.382 57.956 5.754 40.043 12.401 15.762 36.65 9.393 54.254 27.305z"
23
+ />
24
+ <path
25
+ d="M57.42 79.029L43.781 82.603 33.888 72.543 37.632 58.91 51.244 55.334 61.138 65.395z"
26
+ />
27
+ <path
28
+ d="M86.963 59.079L67.775 64.128 53.829 49.94 59.066 30.726 78.277 25.679 92.223 39.865z"
29
+ />
30
+ </g>
31
+ </svg>
32
+ Version <%= @alchemy_version %>
33
+ </div>
34
+
1
35
  <p class="center">
2
- <%= image_tag('alchemy/alchemy-logo.svg', width: 267, height: 91) %>
3
- </p>
4
- <h2 class="center">
5
- v<%= @alchemy_version %><br>
6
36
  <small>
7
- Ruby v<%= RUBY_VERSION %>, Rails v<%= Rails.version %>
37
+ Ruby <%= RUBY_VERSION %>, Rails <%= Rails.version %>
8
38
  </small>
9
- </h2>
39
+ </p>
10
40
 
11
41
  <% if can?(:update_check, :alchemy_admin_dashboard) %>
12
42
  <alchemy-update-check url="<%= alchemy.update_check_path %>">
@@ -24,14 +24,13 @@
24
24
  <%= Alchemy.t(:element_hidden) %>
25
25
  </span>
26
26
  </span>
27
- <%= button_tag({
28
- title: Alchemy.t(element.folded? ? :show_element_content : :hide_element_content),
29
- class: "element-toggle"
30
- }) do %>
31
- <% if element.compact? %>
32
- <%= render_icon "more-2" %>
33
- <% else %>
34
- <%= render_icon element.folded? ? "arrow-left-s" : "arrow-down-s" %>
27
+ <sl-tooltip content="<%= Alchemy.t(element.folded? ? :show_element_content : :hide_element_content) %>">
28
+ <%= button_tag(class: "element-toggle") do %>
29
+ <% if element.compact? %>
30
+ <%= render_icon "more-2" %>
31
+ <% else %>
32
+ <%= render_icon element.folded? ? "arrow-left-s" : "arrow-down-s" %>
33
+ <% end %>
35
34
  <% end %>
36
- <% end %>
35
+ </sl-tooltip>
37
36
  </div>
@@ -16,7 +16,11 @@
16
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
- <%= f.input :url, input_html: { disabled: node.page }, hint: Alchemy.t(:node_url_hint) %>
19
+ <%= f.input :url, as: :string, input_html: {
20
+ disabled: node.page,
21
+ pattern: '/.*|[a-zA-Z][\w\+\-\.]*://.+',
22
+ title: Alchemy.t(:node_url_hint)
23
+ }, hint: Alchemy.t(:node_url_hint) %>
20
24
  <%= f.input :title %>
21
25
  <%= f.input :nofollow %>
22
26
  <%= f.input :external %>
@@ -35,7 +35,7 @@
35
35
  <% end %>
36
36
  <% else %>
37
37
  <div id="pictures" class="picture-size--<%= @size %>">
38
- <%= render partial: 'picture', collection: @pictures %>
38
+ <%= render partial: "picture", collection: @pictures, locals: {picture_offset: picture_offset} %>
39
39
  </div>
40
40
  <% end %>
41
41
  <% end %>
@@ -1,5 +1,14 @@
1
1
  <%= turbo_frame_tag(@picture) do %>
2
- <%= alchemy_form_for [alchemy, :admin, @picture], class: "picture-form" do |f| %>
2
+ <%= alchemy_form_for @picture,
3
+ url: alchemy.admin_picture_path(
4
+ @picture,
5
+ search_filter_params.merge(
6
+ size: @size,
7
+ picture_index: picture_index
8
+ ).to_h
9
+ ),
10
+ remote: false,
11
+ class: "picture-form" do |f| %>
3
12
  <%= f.input :name %>
4
13
  <%= render "alchemy/admin/pictures/picture_description_field", f: f %>
5
14
  <%= render Alchemy::Admin::TagsAutocomplete.new(additional_class: "input") do %>
@@ -7,10 +16,6 @@
7
16
  <%= f.text_field :tag_list, value: f.object.tag_list.join(",") %>
8
17
  <small class="hint"><%= Alchemy.t('Please seperate the tags with commata') %></small>
9
18
  <% end %>
10
- <%= hidden_field_tag :q, search_filter_params[:q] %>
11
- <%= hidden_field_tag :size, @size %>
12
- <%= hidden_field_tag :tagged_with, search_filter_params[:tagged_with] %>
13
- <%= hidden_field_tag :filter, search_filter_params[:filter] %>
14
19
  <%= f.submit Alchemy.t(:save) %>
15
20
  <% end %>
16
21
  <% end %>
@@ -1,11 +1,3 @@
1
- <% picture_path = alchemy.admin_picture_path(
2
- picture,
3
- search_filter_params.merge(
4
- page: params[:page],
5
- size: @size.presence
6
- ).to_h
7
- ) %>
8
-
9
1
  <div class="picture_thumbnail <%= @size %>" id="picture_<%= picture.id %>" name="<%= picture.name %>">
10
2
  <span class="picture_tool select">
11
3
  <%= check_box_tag "picture_ids[]", picture.id %>
@@ -16,7 +8,13 @@
16
8
  <%= link_to_confirm_dialog(
17
9
  render_icon("delete-bin-2"),
18
10
  Alchemy.t(:confirm_to_delete_image_from_server),
19
- picture_path
11
+ alchemy.admin_picture_path(
12
+ picture,
13
+ search_filter_params.merge(
14
+ page: params[:page],
15
+ size: @size.presence
16
+ ).to_h
17
+ )
20
18
  ) -%>
21
19
  </sl-tooltip>
22
20
  </div>
@@ -24,9 +22,16 @@
24
22
  <% picture_url = picture.thumbnail_url(size: preview_size(@size)) %>
25
23
  <% image = picture_url ? image_tag(picture_url, alt: picture.name) : '<alchemy-icon name="file-damage"></alchemy-icon>'.html_safe %>
26
24
  <% if can?(:edit, picture) %>
25
+ <% picture_index ||= picture_offset + picture_iteration.index %>
27
26
  <%= link_to(
28
27
  image,
29
- picture_path,
28
+ alchemy.admin_picture_path(
29
+ picture,
30
+ search_filter_params.merge(
31
+ picture_index: picture_index.to_i + 1,
32
+ size: @size.presence
33
+ ).to_h
34
+ ),
30
35
  class: 'thumbnail_background'
31
36
  ) %>
32
37
  <% else %>
@@ -9,12 +9,11 @@
9
9
  <div class="picture-overlay-navigation">
10
10
  <% if @previous %>
11
11
  <%= link_to alchemy.admin_picture_path(
12
- id: :previous,
13
- q: search_filter_params[:q],
14
- page: @previous,
15
- tagged_with: search_filter_params[:tagged_with],
16
- size: @size,
17
- filter: search_filter_params[:filter]
12
+ :previous,
13
+ search_filter_params.merge(
14
+ picture_index: @previous,
15
+ size: @size
16
+ ).to_h
18
17
  ),
19
18
  class: "previous-picture",
20
19
  remote: true do %>
@@ -23,12 +22,11 @@
23
22
  <% end %>
24
23
  <% if @next %>
25
24
  <%= link_to alchemy.admin_picture_path(
26
- id: :next,
27
- q: search_filter_params[:q],
28
- page: @next,
29
- tagged_with: search_filter_params[:tagged_with],
30
- size: @size,
31
- filter: search_filter_params[:filter]
25
+ :next,
26
+ search_filter_params.merge(
27
+ picture_index: @next,
28
+ size: @size
29
+ ).to_h
32
30
  ),
33
31
  class: "next-picture",
34
32
  remote: true do %>
@@ -38,7 +36,7 @@
38
36
  </div>
39
37
 
40
38
  <div class="picture-details-overlay">
41
- <%= render 'form' %>
39
+ <%= render 'form', picture_index: @previous || @next || 0 %>
42
40
  <hr>
43
41
  <%= render 'infos' %>
44
42
  </div>
@@ -2,5 +2,5 @@
2
2
  <%= @message[:body] %>
3
3
  </alchemy-growl>
4
4
  <%= turbo_stream.replace("picture_#{@picture.id}") do %>
5
- <%= render "picture", picture: @picture %>
5
+ <%= render "picture", picture: @picture, picture_index: params[:picture_index] %>
6
6
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <% file_types = Alchemy.config.uploader.allowed_filetypes[object.class.model_name.collection] || ['*'] %>
2
- <% accept = file_types == ["*"] ? false : file_types.map {|type| ".#{type}"}.join(", ") %>
2
+ <% accept = file_types.to_a == ["*"] ? nil : file_types.map {|type| ".#{type}"}.join(", ") %>
3
3
 
4
4
  <alchemy-uploader dropzone="<%= local_assigns[:dropzone] || "#main_content" %>">
5
5
  <%= form_for [:admin, object], html: { multipart: true, class: 'upload-button' } do |f| %>
@@ -14,7 +14,7 @@
14
14
  <%= stylesheet_link_tag('alchemy/theme', media: 'screen', 'data-turbo-track' => true) %>
15
15
  <%= stylesheet_link_tag('alchemy/admin', media: 'screen', 'data-turbo-track' => true) %>
16
16
  <%= stylesheet_link_tag('alchemy/admin/print', media: 'print', 'data-turbo-track' => true) %>
17
- <% Alchemy.admin_stylesheets.each do |stylesheet| %>
17
+ <% Alchemy.config.admin_stylesheets.each do |stylesheet| %>
18
18
  <%= stylesheet_link_tag(stylesheet, 'data-turbo-track' => true) %>
19
19
  <% end %>
20
20
  <%= yield :stylesheets %>
@@ -29,7 +29,7 @@
29
29
  <%= render 'alchemy/admin/tinymce/setup' %>
30
30
  <%= render 'alchemy/admin/partials/routes' %>
31
31
  <%= javascript_importmap_tags("alchemy_admin", importmap: Alchemy.importmap) %>
32
- <% Alchemy.admin_js_imports.each do |path| %>
32
+ <% Alchemy.config.admin_js_imports.each do |path| %>
33
33
  <script type="module">
34
34
  import "<%= path %>"
35
35
  </script>
@@ -83,10 +83,7 @@
83
83
  <% end %>
84
84
  <div id="user_info">
85
85
  <%= current_alchemy_user_name %>
86
- <% if Alchemy::I18n.available_locales.length > 1 %>
87
- <%= select_tag 'change_locale',
88
- options_for_select(translations_for_select, ::I18n.locale) %>
89
- <% end %>
86
+ <%= render Alchemy::Admin::LocaleSelect.new %>
90
87
  </div>
91
88
  </div>
92
89
  <div id="toolbar">