alchemy_cms 7.2.8 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +97 -23
- data/Gemfile +3 -11
- data/Rakefile +1 -0
- data/alchemy_cms.gemspec +7 -7
- data/app/assets/builds/alchemy/admin/print.css +1 -0
- data/app/assets/builds/alchemy/admin/print.css.map +1 -0
- data/app/assets/builds/alchemy/admin.css +1 -0
- data/app/assets/builds/alchemy/admin.css.map +1 -0
- data/app/assets/builds/alchemy/welcome.css +1 -0
- data/app/assets/builds/alchemy/welcome.css.map +1 -0
- data/app/assets/builds/tinymce/skins/content/alchemy/content.css +1 -0
- data/app/assets/builds/tinymce/skins/content/alchemy/content.css.map +1 -0
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.css.map +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css.map +1 -0
- data/app/assets/config/alchemy_manifest.js +1 -5
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +4 -0
- data/app/assets/stylesheets/alchemy/{_custom-properties.scss → _custom-properties.css} +28 -25
- data/app/assets/stylesheets/alchemy/_deprecated_variables.scss +41 -0
- data/app/assets/stylesheets/alchemy/_deprecation.scss +17 -0
- data/app/assets/stylesheets/alchemy/_extends.scss +1 -1
- data/app/assets/stylesheets/alchemy/_mixins.scss +20 -23
- data/app/assets/stylesheets/alchemy/_variables.scss +98 -94
- data/app/assets/stylesheets/alchemy/{archive.scss → admin/archive.scss} +23 -23
- data/app/assets/stylesheets/alchemy/{attachment-select.scss → admin/attachment-select.scss} +2 -2
- data/app/assets/stylesheets/alchemy/{attachments.scss → admin/attachments.scss} +4 -4
- data/app/assets/stylesheets/alchemy/{base.scss → admin/base.scss} +9 -9
- data/app/assets/stylesheets/alchemy/{buttons.scss → admin/buttons.scss} +3 -3
- data/app/assets/stylesheets/alchemy/{clipboard.scss → admin/clipboard.scss} +9 -6
- data/app/assets/stylesheets/alchemy/{dashboard.scss → admin/dashboard.scss} +8 -8
- data/app/assets/stylesheets/alchemy/{dialogs.scss → admin/dialogs.scss} +20 -20
- data/app/assets/stylesheets/alchemy/{elements.scss → admin/elements.scss} +129 -89
- data/app/assets/stylesheets/alchemy/{errors.scss → admin/errors.scss} +22 -6
- data/app/assets/stylesheets/alchemy/{flash.scss → admin/flash.scss} +3 -3
- data/app/assets/stylesheets/alchemy/{flatpickr.scss → admin/flatpickr.scss} +55 -35
- data/app/assets/stylesheets/alchemy/{form_fields.scss → admin/form_fields.scss} +8 -6
- data/app/assets/stylesheets/alchemy/{forms.scss → admin/forms.scss} +20 -16
- data/app/assets/stylesheets/alchemy/{frame.scss → admin/frame.scss} +9 -9
- data/app/assets/stylesheets/alchemy/{image_library.scss → admin/image_library.scss} +34 -33
- data/app/assets/stylesheets/alchemy/admin/labels.scss +3 -0
- data/app/assets/stylesheets/alchemy/{list_filter.scss → admin/list_filter.scss} +4 -4
- data/app/assets/stylesheets/alchemy/{lists.scss → admin/lists.scss} +9 -7
- data/app/assets/stylesheets/alchemy/{navigation.scss → admin/navigation.scss} +17 -17
- data/app/assets/stylesheets/alchemy/{node-select.scss → admin/node-select.scss} +5 -5
- data/app/assets/stylesheets/alchemy/{nodes.scss → admin/nodes.scss} +11 -11
- data/app/assets/stylesheets/alchemy/{notices.scss → admin/notices.scss} +11 -7
- data/app/assets/stylesheets/alchemy/{page-select.scss → admin/page-select.scss} +10 -10
- data/app/assets/stylesheets/alchemy/{pagination.scss → admin/pagination.scss} +10 -10
- data/app/assets/stylesheets/alchemy/{print.scss → admin/print.scss} +2 -6
- data/app/assets/stylesheets/alchemy/{resource_info.scss → admin/resource_info.scss} +6 -7
- data/app/assets/stylesheets/alchemy/{search.scss → admin/search.scss} +6 -6
- data/app/assets/stylesheets/alchemy/{selects.scss → admin/selects.scss} +46 -39
- data/app/assets/stylesheets/alchemy/{shoelace.scss → admin/shoelace.scss} +10 -10
- data/app/assets/stylesheets/alchemy/{sitemap.scss → admin/sitemap.scss} +18 -19
- data/app/assets/stylesheets/alchemy/{tables.scss → admin/tables.scss} +26 -22
- data/app/assets/stylesheets/alchemy/admin/tags.scss +158 -0
- data/app/assets/stylesheets/alchemy/{toolbar.scss → admin/toolbar.scss} +10 -10
- data/app/assets/stylesheets/alchemy/{typography.scss → admin/typography.scss} +3 -3
- data/app/assets/stylesheets/alchemy/{upload.scss → admin/upload.scss} +1 -1
- data/app/assets/stylesheets/alchemy/admin.scss +40 -45
- data/app/assets/stylesheets/alchemy/welcome.scss +57 -0
- data/app/assets/stylesheets/tinymce/skins/content/alchemy/{content.min.scss → content.scss} +5 -4
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/{skin.min.scss → skin.scss} +40 -40
- data/app/components/alchemy/admin/resource/action.rb +46 -0
- data/app/components/alchemy/admin/resource/cell.rb +34 -0
- data/app/components/alchemy/admin/resource/header.rb +46 -0
- data/app/components/alchemy/admin/resource/table.rb +153 -0
- data/app/components/alchemy/ingredients/datetime_view.rb +2 -2
- data/app/controllers/alchemy/admin/base_controller.rb +4 -27
- data/app/controllers/alchemy/admin/elements_controller.rb +7 -3
- data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +6 -2
- data/app/controllers/alchemy/admin/pictures_controller.rb +2 -2
- data/app/controllers/alchemy/admin/resources_controller.rb +3 -3
- data/app/controllers/alchemy/base_controller.rb +2 -0
- data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -11
- data/app/decorators/alchemy/ingredient_editor.rb +17 -0
- data/app/helpers/alchemy/admin/pages_helper.rb +6 -10
- data/app/helpers/alchemy/base_helper.rb +2 -2
- data/app/helpers/alchemy/elements_block_helper.rb +13 -1
- data/app/helpers/alchemy/pages_helper.rb +2 -2
- data/app/javascript/alchemy_admin/components/element_editor.js +23 -31
- data/app/javascript/alchemy_admin/components/preview_window.js +2 -3
- data/app/javascript/alchemy_admin/picture_selector.js +38 -10
- data/app/models/alchemy/attachment.rb +0 -8
- data/app/models/alchemy/element/dom_id.rb +1 -0
- data/app/models/alchemy/element/element_ingredients.rb +0 -73
- data/app/models/alchemy/element/presenters.rb +4 -1
- data/app/models/alchemy/element.rb +6 -0
- data/app/models/alchemy/elements_repository.rb +2 -2
- data/app/models/alchemy/ingredient_validator.rb +10 -0
- data/app/models/alchemy/page/page_scopes.rb +1 -1
- data/app/models/alchemy/picture.rb +0 -10
- data/app/models/concerns/alchemy/picture_thumbnails.rb +5 -4
- data/app/views/alchemy/admin/attachments/_files_list.html.erb +74 -16
- data/app/views/alchemy/admin/clipboard/index.html.erb +38 -33
- data/app/views/alchemy/admin/dashboard/_dashboard.html.erb +3 -0
- data/app/views/alchemy/admin/dashboard/_left_column.html.erb +4 -0
- data/app/views/alchemy/admin/dashboard/_right_column.html.erb +9 -0
- data/app/views/alchemy/admin/dashboard/_top.html.erb +12 -0
- data/app/views/alchemy/admin/dashboard/index.html.erb +1 -25
- data/app/views/alchemy/admin/elements/_element.html.erb +1 -2
- data/app/views/alchemy/admin/elements/_form.html.erb +1 -1
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +10 -3
- data/app/views/alchemy/admin/ingredients/update.turbo_stream.erb +7 -0
- data/app/views/alchemy/admin/languages/_table.html.erb +16 -42
- data/app/views/alchemy/admin/nodes/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_table.html.erb +92 -27
- data/app/views/alchemy/admin/pages/edit.html.erb +6 -8
- data/app/views/alchemy/admin/pages/index.html.erb +0 -4
- data/app/views/alchemy/admin/pictures/_form.html.erb +14 -12
- data/app/views/alchemy/admin/pictures/index.html.erb +1 -11
- data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +6 -0
- data/app/views/alchemy/admin/resources/_resource_table.html.erb +3 -0
- data/app/views/alchemy/admin/resources/_table.html.erb +2 -0
- data/app/views/alchemy/admin/resources/index.html.erb +1 -1
- data/app/views/alchemy/admin/sites/index.html.erb +1 -1
- data/app/views/alchemy/admin/styleguide/index.html.erb +0 -4
- data/app/views/alchemy/admin/tags/index.html.erb +15 -14
- data/app/views/alchemy/base/403.html.erb +6 -0
- data/app/views/alchemy/base/500.html.erb +14 -12
- data/app/views/alchemy/ingredients/_datetime_editor.html.erb +13 -11
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +29 -22
- data/app/views/alchemy/ingredients/_link_editor.html.erb +17 -11
- data/app/views/alchemy/ingredients/_page_editor.html.erb +1 -0
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +3 -4
- data/app/views/alchemy/ingredients/_richtext_editor.html.erb +5 -1
- data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -1
- data/app/views/alchemy/ingredients/_text_editor.html.erb +20 -14
- data/app/views/alchemy/ingredients/shared/_picture_css_class.html.erb +6 -0
- data/app/views/layouts/alchemy/admin.html.erb +4 -2
- data/bin/setup +2 -0
- data/bin/start +1 -1
- data/bun.lockb +0 -0
- data/config/alchemy/config.yml +9 -0
- data/config/locales/alchemy.en.yml +8 -29
- data/config/routes.rb +22 -22
- data/lib/alchemy/config.rb +3 -3
- data/lib/alchemy/install/tasks.rb +5 -2
- data/lib/alchemy/resource.rb +4 -14
- data/lib/alchemy/resources_helper.rb +3 -1
- data/lib/alchemy/test_support/capybara_helpers.rb +8 -5
- data/lib/alchemy/test_support/shared_uploader_examples.rb +0 -1
- data/lib/alchemy/upgrader/seven_point_three.rb +52 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -1
- data/lib/generators/alchemy/install/files/article.css +25 -0
- data/lib/generators/alchemy/install/files/custom.css +4 -0
- data/lib/generators/alchemy/install/install_generator.rb +6 -6
- data/lib/tasks/alchemy/upgrade.rake +29 -1
- data/vendor/assets/stylesheets/alchemy_admin/select2.css +1 -0
- data/vendor/assets/stylesheets/jquery.Jcrop.min.css +2 -0
- data/vendor/javascript/shoelace.min.js +62 -63
- data/vendor/javascript/tinymce.min.js +1 -1
- metadata +135 -106
- data/app/assets/images/alchemy/lupe.cur +0 -0
- data/app/assets/stylesheets/alchemy/labels.scss +0 -3
- data/app/assets/stylesheets/alchemy/tags.scss +0 -155
- data/app/assets/stylesheets/alchemy/welcome.sass +0 -49
- data/app/views/alchemy/admin/attachments/_attachment.html.erb +0 -81
- data/app/views/alchemy/admin/languages/_language.html.erb +0 -50
- data/app/views/alchemy/admin/pages/_table_row.html.erb +0 -111
- data/app/views/alchemy/admin/pages/list/_table.html.erb +0 -31
- data/app/views/alchemy/admin/pictures/update.js.erb +0 -6
- data/app/views/alchemy/admin/tags/_tag.html.erb +0 -32
- data/app/views/alchemy/base/update.js.erb +0 -5
- data/lib/generators/alchemy/install/files/all.css +0 -11
- data/lib/generators/alchemy/install/files/article.scss +0 -30
- data/package.json +0 -52
- data/vendor/assets/stylesheets/alchemy_admin/select2.scss +0 -741
- data/vendor/assets/stylesheets/jquery.Jcrop.min.scss +0 -2
- /data/app/assets/stylesheets/alchemy/{fonts.scss → _fonts.scss} +0 -0
- /data/app/assets/stylesheets/alchemy/{hints.scss → admin/hints.scss} +0 -0
- /data/app/assets/stylesheets/alchemy/{icons.scss → admin/icons.scss} +0 -0
- /data/app/assets/stylesheets/alchemy/{images.scss → admin/images.scss} +0 -0
- /data/app/assets/stylesheets/alchemy/{preview_window.scss → admin/preview_window.scss} +0 -0
- /data/app/assets/stylesheets/alchemy/{spinner.scss → admin/spinner.scss} +0 -0
- /data/app/views/alchemy/admin/dashboard/{_locked_pages.html.erb → widgets/_locked_pages.html.erb} +0 -0
- /data/app/views/alchemy/admin/dashboard/{_recent_pages.html.erb → widgets/_recent_pages.html.erb} +0 -0
- /data/app/views/alchemy/admin/dashboard/{_sites.html.erb → widgets/_sites.html.erb} +0 -0
- /data/app/views/alchemy/admin/dashboard/{_users.html.erb → widgets/_users.html.erb} +0 -0
|
@@ -1,34 +1,62 @@
|
|
|
1
1
|
import { on } from "alchemy_admin/utils/events"
|
|
2
2
|
|
|
3
|
+
function toggleCheckboxes(state) {
|
|
4
|
+
document
|
|
5
|
+
.querySelectorAll(".picture_tool.select input[type='checkbox']")
|
|
6
|
+
.forEach((checkbox) => {
|
|
7
|
+
checkbox.checked = state
|
|
8
|
+
checkbox.closest(".picture_thumbnail").classList.toggle("active", state)
|
|
9
|
+
})
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function checkedInputs() {
|
|
13
|
+
return document.querySelectorAll("#picture_archive input:checked")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function editMultiplePicturesUrl(href) {
|
|
17
|
+
const searchParameters = new URLSearchParams()
|
|
18
|
+
checkedInputs().forEach((entry) =>
|
|
19
|
+
searchParameters.append(entry.name, entry.value)
|
|
20
|
+
)
|
|
21
|
+
const url = href + "?" + searchParameters.toString()
|
|
22
|
+
|
|
23
|
+
return url
|
|
24
|
+
}
|
|
25
|
+
|
|
3
26
|
/**
|
|
4
27
|
* Multiple picture select handler for the picture archive.
|
|
5
28
|
*/
|
|
6
29
|
export default function PictureSelector() {
|
|
30
|
+
const selectAllButton = document.querySelector("#select_all_pictures")
|
|
7
31
|
const selectedItemTools = document.querySelector(".selected_item_tools")
|
|
8
|
-
|
|
9
|
-
|
|
32
|
+
|
|
33
|
+
on("click", ".toolbar_buttons", "a#select_all_pictures", (event) => {
|
|
34
|
+
event.preventDefault()
|
|
35
|
+
|
|
36
|
+
selectAllButton.classList.toggle("active")
|
|
37
|
+
|
|
38
|
+
const state = selectAllButton.classList.contains("active")
|
|
39
|
+
|
|
40
|
+
toggleCheckboxes(state)
|
|
41
|
+
|
|
42
|
+
selectedItemTools.classList.toggle("hidden", !state)
|
|
43
|
+
})
|
|
10
44
|
|
|
11
45
|
// make the item toolbar visible and show the checkbox also if it is not hovered anymore
|
|
12
46
|
on("change", ".picture_tool.select", "input", (event) => {
|
|
13
|
-
selectedItemTools.
|
|
14
|
-
checkedInputs().length > 0 ? "block" : "none"
|
|
47
|
+
selectedItemTools.classList.toggle("hidden", checkedInputs().length === 0)
|
|
15
48
|
|
|
16
49
|
const parentElementClassList = event.target.parentElement.classList
|
|
17
50
|
const checked = event.target.checked
|
|
18
51
|
|
|
19
52
|
parentElementClassList.toggle("visible", checked)
|
|
20
|
-
parentElementClassList.toggle("hidden", !checked)
|
|
21
53
|
})
|
|
22
54
|
|
|
23
55
|
// open the edit view in a dialog modal
|
|
24
56
|
on("click", ".selected_item_tools", "a#edit_multiple_pictures", (event) => {
|
|
25
57
|
event.preventDefault()
|
|
26
58
|
|
|
27
|
-
const
|
|
28
|
-
checkedInputs().forEach((entry) =>
|
|
29
|
-
searchParameters.append(entry.name, entry.value)
|
|
30
|
-
)
|
|
31
|
-
const url = event.target.href + "?" + searchParameters.toString()
|
|
59
|
+
const url = editMultiplePicturesUrl(event.target.href)
|
|
32
60
|
|
|
33
61
|
Alchemy.openDialog(url, {
|
|
34
62
|
title: event.target.title,
|
|
@@ -102,14 +102,6 @@ module Alchemy
|
|
|
102
102
|
|
|
103
103
|
# Instance methods
|
|
104
104
|
|
|
105
|
-
def to_jq_upload
|
|
106
|
-
{
|
|
107
|
-
"name" => read_attribute(:file_name),
|
|
108
|
-
"size" => read_attribute(:file_size),
|
|
109
|
-
"error" => errors[:file].join
|
|
110
|
-
}
|
|
111
|
-
end
|
|
112
|
-
|
|
113
105
|
def url(options = {})
|
|
114
106
|
if file
|
|
115
107
|
self.class.url_class.new(self).call(options)
|
|
@@ -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
|
#
|
|
@@ -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)
|
|
@@ -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
|
|
@@ -102,10 +102,11 @@ module Alchemy
|
|
|
102
102
|
|
|
103
103
|
# Show image cropping link for ingredient
|
|
104
104
|
def allow_image_cropping?
|
|
105
|
-
settings[:crop] && picture
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
settings[:crop] && picture &&
|
|
106
|
+
picture.can_be_cropped_to?(
|
|
107
|
+
settings[:size],
|
|
108
|
+
settings[:upsample]
|
|
109
|
+
) && !!picture.image_file
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
private
|
|
@@ -7,22 +7,80 @@
|
|
|
7
7
|
<% end %>
|
|
8
8
|
<% end %>
|
|
9
9
|
<% else %>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
2
|
-
<%= render_message do %>
|
|
3
|
-
|
|
4
|
-
<% end %>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</
|
|
25
|
-
|
|
26
|
-
|
|
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,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
|
-
|
|
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
|
-
<
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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) %>
|