alchemy_cms 6.1.2 → 7.0.0.pre.a
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/.github/workflows/ci.yml +0 -3
- data/.gitignore +1 -6
- data/CHANGELOG.md +22 -8
- data/Gemfile +1 -0
- data/Rakefile +13 -8
- data/alchemy_cms.gemspec +1 -3
- data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +27 -29
- data/app/assets/stylesheets/alchemy/elements.scss +16 -35
- data/app/assets/stylesheets/alchemy/forms.scss +0 -4
- data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
- data/app/controllers/alchemy/admin/attachments_controller.rb +0 -1
- data/app/controllers/alchemy/admin/elements_controller.rb +7 -32
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +1 -1
- data/app/controllers/alchemy/admin/resources_controller.rb +1 -18
- data/app/controllers/alchemy/api/elements_controller.rb +0 -2
- data/app/controllers/alchemy/api/pages_controller.rb +6 -4
- data/app/controllers/alchemy/messages_controller.rb +9 -9
- data/app/controllers/alchemy/pages_controller.rb +19 -28
- data/app/decorators/alchemy/element_editor.rb +10 -30
- data/app/helpers/alchemy/admin/elements_helper.rb +0 -2
- data/app/helpers/alchemy/elements_block_helper.rb +5 -42
- data/app/helpers/alchemy/elements_helper.rb +3 -11
- data/app/helpers/alchemy/pages_helper.rb +0 -4
- data/app/models/alchemy/attachment.rb +6 -3
- data/app/models/alchemy/base_record.rb +2 -0
- data/app/models/alchemy/eager_loading.rb +0 -1
- data/app/models/alchemy/element/element_ingredients.rb +1 -8
- data/app/models/alchemy/element/presenters.rb +9 -25
- data/app/models/alchemy/element.rb +2 -16
- data/app/models/alchemy/ingredient.rb +17 -6
- data/app/models/alchemy/ingredients/audio.rb +2 -0
- data/app/models/alchemy/ingredients/datetime.rb +3 -1
- data/app/models/alchemy/ingredients/file.rb +7 -0
- data/app/models/alchemy/ingredients/headline.rb +6 -0
- data/app/models/alchemy/ingredients/link.rb +2 -0
- data/app/models/alchemy/ingredients/node.rb +2 -0
- data/app/models/alchemy/ingredients/page.rb +2 -0
- data/app/models/alchemy/ingredients/picture.rb +11 -0
- data/app/models/alchemy/ingredients/richtext.rb +6 -0
- data/app/models/alchemy/ingredients/select.rb +1 -0
- data/app/models/alchemy/ingredients/text.rb +8 -0
- data/app/models/alchemy/ingredients/video.rb +2 -0
- data/app/models/alchemy/node.rb +9 -6
- data/app/models/alchemy/page/page_elements.rb +5 -26
- data/app/models/alchemy/page/page_layouts.rb +0 -14
- data/app/models/alchemy/page/page_natures.rb +0 -10
- data/app/models/alchemy/page.rb +0 -8
- data/app/models/alchemy/picture/transformations.rb +0 -30
- data/app/models/alchemy/picture/url.rb +1 -1
- data/app/models/alchemy/picture.rb +12 -10
- data/app/models/alchemy/picture_thumb/create.rb +7 -18
- data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
- data/app/models/alchemy/picture_thumb.rb +10 -10
- data/app/models/concerns/alchemy/picture_thumbnails.rb +2 -2
- data/app/serializers/alchemy/element_serializer.rb +1 -6
- data/app/services/alchemy/delete_elements.rb +1 -7
- data/app/services/alchemy/duplicate_element.rb +1 -6
- data/app/views/alchemy/admin/elements/_element.html.erb +5 -22
- data/app/views/alchemy/admin/elements/create.js.erb +1 -1
- data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
- data/app/views/alchemy/admin/elements/order.js.erb +1 -1
- data/app/views/alchemy/admin/elements/update.js.erb +1 -2
- data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +3 -6
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
- data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
- data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
- data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
- data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
- data/app/views/layouts/alchemy/admin.html.erb +5 -1
- data/config/alchemy/config.yml +6 -6
- data/config/brakeman.ignore +56 -57
- data/config/locales/alchemy.en.yml +98 -112
- data/config/routes.rb +1 -16
- data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
- data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
- data/lib/alchemy/config.rb +2 -2
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/errors.rb +0 -11
- data/lib/alchemy/hints.rb +10 -10
- data/lib/alchemy/install/tasks.rb +7 -1
- data/lib/alchemy/permissions.rb +0 -13
- data/lib/alchemy/routing_constraints.rb +3 -3
- data/lib/alchemy/searchable_resource.rb +38 -0
- data/lib/alchemy/tasks/tidy.rb +0 -38
- data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
- data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
- data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
- data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
- data/lib/alchemy/tinymce.rb +1 -18
- data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
- data/lib/alchemy/upgrader/tasks/.keep +0 -0
- data/lib/alchemy/upgrader.rb +8 -3
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +0 -19
- data/lib/alchemy_cms.rb +2 -3
- data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
- data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
- data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
- data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
- data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
- data/lib/generators/alchemy/install/files/application.html.erb +1 -1
- data/lib/generators/alchemy/install/install_generator.rb +18 -22
- data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
- data/lib/non_stupid_digest_assets.rb +55 -0
- data/lib/tasks/alchemy/thumbnails.rake +2 -21
- data/lib/tasks/alchemy/tidy.rake +1 -12
- data/lib/tasks/alchemy/upgrade.rake +10 -47
- data/package/dist/admin.js +16 -0
- data/package/dist/admin.js.map +7 -0
- data/package.json +5 -3
- metadata +15 -154
- data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
- data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
- data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
- data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
- data/app/controllers/alchemy/api/contents_controller.rb +0 -52
- data/app/decorators/alchemy/content_editor.rb +0 -119
- data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
- data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
- data/app/models/alchemy/content/factory.rb +0 -143
- data/app/models/alchemy/content.rb +0 -247
- data/app/models/alchemy/element/element_contents.rb +0 -200
- data/app/models/alchemy/element/element_essences.rb +0 -133
- data/app/models/alchemy/essence_audio.rb +0 -13
- data/app/models/alchemy/essence_boolean.rb +0 -20
- data/app/models/alchemy/essence_date.rb +0 -25
- data/app/models/alchemy/essence_file.rb +0 -49
- data/app/models/alchemy/essence_headline.rb +0 -41
- data/app/models/alchemy/essence_html.rb +0 -23
- data/app/models/alchemy/essence_link.rb +0 -21
- data/app/models/alchemy/essence_node.rb +0 -19
- data/app/models/alchemy/essence_page.rb +0 -17
- data/app/models/alchemy/essence_picture.rb +0 -67
- data/app/models/alchemy/essence_picture_view.rb +0 -90
- data/app/models/alchemy/essence_richtext.rb +0 -44
- data/app/models/alchemy/essence_select.rb +0 -19
- data/app/models/alchemy/essence_text.rb +0 -23
- data/app/models/alchemy/essence_video.rb +0 -13
- data/app/serializers/alchemy/content_serializer.rb +0 -17
- data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
- data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
- data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
- data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
- data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
- data/app/views/alchemy/admin/contents/create.js.erb +0 -21
- data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
- data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
- data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
- data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
- data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
- data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
- data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
- data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
- data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
- data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
- data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
- data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
- data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
- data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
- data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
- data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
- data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
- data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
- data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
- data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
- data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
- data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
- data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
- data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
- data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
- data/app/views/alchemy/pages/show.rss.builder +0 -21
- data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
- data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
- data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
- data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
- data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
- data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
- data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
- data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
- data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
- data/db/migrate/20201207131309_create_page_versions.rb +0 -19
- data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
- data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
- data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
- data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
- data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
- data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
- data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
- data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
- data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
- data/lib/alchemy/essence.rb +0 -250
- data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
- data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
- data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
- data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
- data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
- data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
- data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
- data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
- data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -74
- data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
- data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
- data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
|
@@ -21,9 +21,7 @@
|
|
|
21
21
|
#
|
|
22
22
|
|
|
23
23
|
require_dependency "alchemy/element/definitions"
|
|
24
|
-
require_dependency "alchemy/element/element_contents"
|
|
25
24
|
require_dependency "alchemy/element/element_ingredients"
|
|
26
|
-
require_dependency "alchemy/element/element_essences"
|
|
27
25
|
require_dependency "alchemy/element/presenters"
|
|
28
26
|
|
|
29
27
|
module Alchemy
|
|
@@ -38,7 +36,6 @@ module Alchemy
|
|
|
38
36
|
"amount",
|
|
39
37
|
"autogenerate",
|
|
40
38
|
"nestable_elements",
|
|
41
|
-
"contents",
|
|
42
39
|
"hint",
|
|
43
40
|
"ingredients",
|
|
44
41
|
"taggable",
|
|
@@ -59,10 +56,6 @@ module Alchemy
|
|
|
59
56
|
|
|
60
57
|
stampable stamper_class_name: Alchemy.user_class.name
|
|
61
58
|
|
|
62
|
-
has_many :contents, dependent: :destroy, inverse_of: :element
|
|
63
|
-
|
|
64
|
-
deprecate contents: :ingredients, deprecator: Alchemy::Deprecation
|
|
65
|
-
|
|
66
59
|
before_destroy :delete_all_nested_elements
|
|
67
60
|
|
|
68
61
|
has_many :all_nested_elements,
|
|
@@ -95,9 +88,7 @@ module Alchemy
|
|
|
95
88
|
validates_presence_of :name, on: :create
|
|
96
89
|
validates_format_of :name, on: :create, with: NAME_REGEXP
|
|
97
90
|
|
|
98
|
-
attr_accessor :autogenerate_contents
|
|
99
91
|
attr_accessor :autogenerate_nested_elements
|
|
100
|
-
after_create :create_contents, unless: -> { autogenerate_contents == false }
|
|
101
92
|
after_create :generate_nested_elements, unless: -> { autogenerate_nested_elements == false }
|
|
102
93
|
|
|
103
94
|
after_update :touch_touchable_pages
|
|
@@ -105,7 +96,6 @@ module Alchemy
|
|
|
105
96
|
scope :published, -> { where(public: true) }
|
|
106
97
|
scope :hidden, -> { where(public: false) }
|
|
107
98
|
scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
|
|
108
|
-
scope :available, -> { published }
|
|
109
99
|
scope :named, ->(names) { where(name: names) }
|
|
110
100
|
scope :excluded, ->(names) { where.not(name: names) }
|
|
111
101
|
scope :fixed, -> { where(fixed: true) }
|
|
@@ -119,8 +109,6 @@ module Alchemy
|
|
|
119
109
|
|
|
120
110
|
# Concerns
|
|
121
111
|
include Definitions
|
|
122
|
-
include ElementContents
|
|
123
|
-
include ElementEssences
|
|
124
112
|
include ElementIngredients
|
|
125
113
|
include Presenters
|
|
126
114
|
|
|
@@ -157,7 +145,7 @@ module Alchemy
|
|
|
157
145
|
@_dom_id_class = klass
|
|
158
146
|
end
|
|
159
147
|
|
|
160
|
-
# This methods does a copy of source and all
|
|
148
|
+
# This methods does a copy of source and all its ingredients.
|
|
161
149
|
#
|
|
162
150
|
# == Options
|
|
163
151
|
#
|
|
@@ -192,8 +180,6 @@ module Alchemy
|
|
|
192
180
|
|
|
193
181
|
all_from_clipboard(clipboard).where(name: parent_element.definition["nestable_elements"])
|
|
194
182
|
end
|
|
195
|
-
|
|
196
|
-
deprecate available: :published, deprecator: Alchemy::Deprecation
|
|
197
183
|
end
|
|
198
184
|
|
|
199
185
|
# Returns next public element from same page.
|
|
@@ -277,7 +263,7 @@ module Alchemy
|
|
|
277
263
|
# Elements are defined in the +config/alchemy/elements.yml+ file
|
|
278
264
|
#
|
|
279
265
|
# - name: article
|
|
280
|
-
#
|
|
266
|
+
# ingredients:
|
|
281
267
|
# ...
|
|
282
268
|
#
|
|
283
269
|
# == Override the view
|
|
@@ -13,11 +13,13 @@ module Alchemy
|
|
|
13
13
|
belongs_to :element, touch: true, class_name: "Alchemy::Element", inverse_of: :ingredients
|
|
14
14
|
belongs_to :related_object, polymorphic: true, optional: true
|
|
15
15
|
|
|
16
|
+
has_one :page, through: :element, class_name: "Alchemy::Page"
|
|
17
|
+
|
|
16
18
|
after_initialize :set_default_value,
|
|
17
19
|
if: -> { definition.key?(:default) && value.nil? }
|
|
18
20
|
|
|
19
21
|
validates :type, presence: true
|
|
20
|
-
validates :role, presence: true
|
|
22
|
+
validates :role, presence: true, uniqueness: { scope: :element_id, case_sensitive: false }
|
|
21
23
|
|
|
22
24
|
validates_with Alchemy::IngredientValidator, on: :update, if: :has_validations?
|
|
23
25
|
|
|
@@ -76,11 +78,16 @@ module Alchemy
|
|
|
76
78
|
default: Alchemy.t("ingredient_roles.#{role}", default: role.humanize),
|
|
77
79
|
)
|
|
78
80
|
end
|
|
79
|
-
end
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
# Allow to define settings on the ingredient definition
|
|
83
|
+
def allow_settings(settings)
|
|
84
|
+
@allowed_settings = Array(settings)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Allowed settings on the ingredient
|
|
88
|
+
def allowed_settings
|
|
89
|
+
@allowed_settings ||= []
|
|
90
|
+
end
|
|
84
91
|
end
|
|
85
92
|
|
|
86
93
|
# The value or the related object if present
|
|
@@ -97,7 +104,7 @@ module Alchemy
|
|
|
97
104
|
#
|
|
98
105
|
# @param key [Symbol] - The hash key you want to fetch the value from
|
|
99
106
|
# @param options [Hash] - An optional Hash that can override the settings.
|
|
100
|
-
# Normally passed as options hash into the
|
|
107
|
+
# Normally passed as options hash into the ingredient
|
|
101
108
|
# editor view.
|
|
102
109
|
def settings_value(key, options = {})
|
|
103
110
|
settings.merge(options || {})[key.to_sym]
|
|
@@ -164,6 +171,10 @@ module Alchemy
|
|
|
164
171
|
role
|
|
165
172
|
end
|
|
166
173
|
|
|
174
|
+
def hint_translation_scope
|
|
175
|
+
"ingredient_hints"
|
|
176
|
+
end
|
|
177
|
+
|
|
167
178
|
def set_default_value
|
|
168
179
|
self.value = default_value
|
|
169
180
|
end
|
|
@@ -5,6 +5,8 @@ module Alchemy
|
|
|
5
5
|
# A datetime value
|
|
6
6
|
#
|
|
7
7
|
class Datetime < Alchemy::Ingredient
|
|
8
|
+
allow_settings %i[date_format]
|
|
9
|
+
|
|
8
10
|
def value
|
|
9
11
|
ActiveRecord::Type::DateTime.new.cast(self[:value])
|
|
10
12
|
end
|
|
@@ -13,7 +15,7 @@ module Alchemy
|
|
|
13
15
|
def preview_text(_maxlength = nil)
|
|
14
16
|
return "" unless value
|
|
15
17
|
|
|
16
|
-
::I18n.l(value, format: :'alchemy.
|
|
18
|
+
::I18n.l(value, format: :'alchemy.ingredient_date')
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -27,6 +27,17 @@ module Alchemy
|
|
|
27
27
|
|
|
28
28
|
related_object_alias :picture, class_name: "Alchemy::Picture"
|
|
29
29
|
|
|
30
|
+
allow_settings %i[
|
|
31
|
+
crop
|
|
32
|
+
css_classes
|
|
33
|
+
fixed_ratio
|
|
34
|
+
linkable
|
|
35
|
+
size
|
|
36
|
+
sizes
|
|
37
|
+
srcset
|
|
38
|
+
upsample
|
|
39
|
+
]
|
|
40
|
+
|
|
30
41
|
# The first 30 characters of the pictures name
|
|
31
42
|
#
|
|
32
43
|
# Used by the Element#preview_text method.
|
data/app/models/alchemy/node.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Alchemy
|
|
|
4
4
|
class Node < BaseRecord
|
|
5
5
|
VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/
|
|
6
6
|
|
|
7
|
-
before_destroy :
|
|
7
|
+
before_destroy :check_if_related_node_ingredients_present
|
|
8
8
|
|
|
9
9
|
acts_as_nested_set scope: "language_id", touch: true
|
|
10
10
|
stampable stamper_class_name: Alchemy.user_class.name
|
|
@@ -14,7 +14,10 @@ module Alchemy
|
|
|
14
14
|
|
|
15
15
|
has_one :site, through: :language
|
|
16
16
|
|
|
17
|
-
has_many :
|
|
17
|
+
has_many :node_ingredients,
|
|
18
|
+
class_name: "Alchemy::Ingredients::Node",
|
|
19
|
+
foreign_key: :related_object_id,
|
|
20
|
+
inverse_of: :related_object
|
|
18
21
|
|
|
19
22
|
before_validation :translate_root_menu_name, if: -> { root? }
|
|
20
23
|
before_validation :set_menu_type_from_root, unless: -> { root? }
|
|
@@ -76,10 +79,10 @@ module Alchemy
|
|
|
76
79
|
|
|
77
80
|
private
|
|
78
81
|
|
|
79
|
-
def
|
|
80
|
-
|
|
81
|
-
if
|
|
82
|
-
errors.add(:base, :
|
|
82
|
+
def check_if_related_node_ingredients_present
|
|
83
|
+
dependent_node_ingredients = self_and_descendants.flat_map(&:node_ingredients)
|
|
84
|
+
if dependent_node_ingredients.any?
|
|
85
|
+
errors.add(:base, :node_ingredients_present, page_names: dependent_node_ingredients.map { |i| i.element&.page&.name }.to_sentence)
|
|
83
86
|
throw(:abort)
|
|
84
87
|
end
|
|
85
88
|
end
|
|
@@ -19,7 +19,7 @@ module Alchemy
|
|
|
19
19
|
has_many :fixed_elements, -> { fixed.published }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
has_many :
|
|
22
|
+
has_many :ingredients, through: :elements
|
|
23
23
|
has_and_belongs_to_many :to_be_swept_elements, -> { distinct },
|
|
24
24
|
class_name: "Alchemy::Element",
|
|
25
25
|
join_table: ElementToPage.table_name
|
|
@@ -58,17 +58,17 @@ module Alchemy
|
|
|
58
58
|
#
|
|
59
59
|
# - name: headline
|
|
60
60
|
# unique: true
|
|
61
|
-
#
|
|
61
|
+
# ingredients:
|
|
62
62
|
# - name: headline
|
|
63
|
-
# type:
|
|
63
|
+
# type: Text
|
|
64
64
|
#
|
|
65
65
|
# == Example of limited element:
|
|
66
66
|
#
|
|
67
67
|
# - name: article
|
|
68
68
|
# amount: 2
|
|
69
|
-
#
|
|
69
|
+
# ingredients:
|
|
70
70
|
# - name: text
|
|
71
|
-
# type:
|
|
71
|
+
# type: Richtext
|
|
72
72
|
#
|
|
73
73
|
def available_element_definitions(only_element_named = nil)
|
|
74
74
|
@_element_definitions ||= if only_element_named
|
|
@@ -156,27 +156,6 @@ module Alchemy
|
|
|
156
156
|
end
|
|
157
157
|
end
|
|
158
158
|
|
|
159
|
-
# Returns all elements that should be feeded via rss.
|
|
160
|
-
#
|
|
161
|
-
# Define feedable elements in your +page_layouts.yml+:
|
|
162
|
-
#
|
|
163
|
-
# - name: news
|
|
164
|
-
# feed: true
|
|
165
|
-
# feed_elements: [element_name, element_2_name]
|
|
166
|
-
#
|
|
167
|
-
def feed_elements
|
|
168
|
-
elements.named(definition["feed_elements"])
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Returns an array of all EssenceRichtext contents ids from not folded elements
|
|
172
|
-
#
|
|
173
|
-
def richtext_contents_ids
|
|
174
|
-
Alchemy::Content.joins(:element)
|
|
175
|
-
.where(Element.table_name => { page_version_id: draft_version.id, folded: false })
|
|
176
|
-
.select(&:has_tinymce?)
|
|
177
|
-
.collect(&:id)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
159
|
# Returns an array of all Richtext ingredients ids from not folded elements
|
|
181
160
|
#
|
|
182
161
|
def richtext_ingredients_ids
|
|
@@ -23,20 +23,6 @@ module Alchemy
|
|
|
23
23
|
mapped_layouts_for_select(selectable_layouts(language_id, layoutpages: layoutpages))
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
# Returns page layouts including given layout ready for Rails' select form helper.
|
|
27
|
-
#
|
|
28
|
-
def layouts_with_own_for_select(page_layout_name, language_id, layoutpages: false)
|
|
29
|
-
layouts = selectable_layouts(language_id, layoutpages: layoutpages)
|
|
30
|
-
if layouts.detect { |l| l["name"] == page_layout_name }.nil?
|
|
31
|
-
@map_array = [[human_layout_name(page_layout_name), page_layout_name]]
|
|
32
|
-
else
|
|
33
|
-
@map_array = []
|
|
34
|
-
end
|
|
35
|
-
mapped_layouts_for_select(layouts)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
deprecate :layouts_with_own_for_select, deprecator: Alchemy::Deprecation
|
|
39
|
-
|
|
40
26
|
# Returns all layouts that can be used for creating a new page.
|
|
41
27
|
#
|
|
42
28
|
# It removes all layouts from available layouts that are unique and already taken and that are marked as hide.
|
|
@@ -17,12 +17,6 @@ module Alchemy
|
|
|
17
17
|
public_until ? public_until - Time.current : nil
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def taggable?
|
|
21
|
-
definition["taggable"] == true
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
deprecate :taggable?, deprecator: Alchemy::Deprecation
|
|
25
|
-
|
|
26
20
|
def rootpage?
|
|
27
21
|
!new_record? && parent_id.blank?
|
|
28
22
|
end
|
|
@@ -33,10 +27,6 @@ module Alchemy
|
|
|
33
27
|
folded_pages.where(user_id: user_id, folded: true).any?
|
|
34
28
|
end
|
|
35
29
|
|
|
36
|
-
def contains_feed?
|
|
37
|
-
definition["feed"]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
30
|
# Returns an Array of Alchemy roles which are able to edit this template
|
|
41
31
|
#
|
|
42
32
|
# # config/alchemy/page_layouts.yml
|
data/app/models/alchemy/page.rb
CHANGED
|
@@ -163,14 +163,6 @@ module Alchemy
|
|
|
163
163
|
# site_name accessor
|
|
164
164
|
delegate :name, to: :site, prefix: true, allow_nil: true
|
|
165
165
|
|
|
166
|
-
# Old public_on and public_until attributes for historical reasons
|
|
167
|
-
#
|
|
168
|
-
# These attributes now exist on the page versions
|
|
169
|
-
#
|
|
170
|
-
attr_readonly :legacy_public_on, :legacy_public_until
|
|
171
|
-
deprecate :legacy_public_on, deprecator: Alchemy::Deprecation
|
|
172
|
-
deprecate :legacy_public_until, deprecator: Alchemy::Deprecation
|
|
173
|
-
|
|
174
166
|
# Class methods
|
|
175
167
|
#
|
|
176
168
|
class << self
|
|
@@ -33,36 +33,6 @@ module Alchemy
|
|
|
33
33
|
image_file.thumbnail(upsample ? size : "#{size}>")
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# Returns true if picture's width is greater than it's height
|
|
37
|
-
#
|
|
38
|
-
def landscape_format?
|
|
39
|
-
image_file.landscape?
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
alias_method :landscape?, :landscape_format?
|
|
43
|
-
deprecate landscape_format?: "Use image_file.landscape? instead", deprecator: Alchemy::Deprecation
|
|
44
|
-
deprecate landscape?: "Use image_file.landscape? instead", deprecator: Alchemy::Deprecation
|
|
45
|
-
|
|
46
|
-
# Returns true if picture's width is smaller than it's height
|
|
47
|
-
#
|
|
48
|
-
def portrait_format?
|
|
49
|
-
image_file.portrait?
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
alias_method :portrait?, :portrait_format?
|
|
53
|
-
deprecate portrait_format?: "Use image_file.portrait? instead", deprecator: Alchemy::Deprecation
|
|
54
|
-
deprecate portrait?: "Use image_file.portrait? instead", deprecator: Alchemy::Deprecation
|
|
55
|
-
|
|
56
|
-
# Returns true if picture's width and height is equal
|
|
57
|
-
#
|
|
58
|
-
def square_format?
|
|
59
|
-
image_file.aspect_ratio == 1.0
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
alias_method :square?, :square_format?
|
|
63
|
-
deprecate square_format?: "Use image_file.aspect_ratio instead", deprecator: Alchemy::Deprecation
|
|
64
|
-
deprecate square?: "Use image_file.aspect_ratio instead", deprecator: Alchemy::Deprecation
|
|
65
|
-
|
|
66
36
|
# Returns true if the class we're included in has a meaningful render_size attribute
|
|
67
37
|
#
|
|
68
38
|
def render_size?
|
|
@@ -36,7 +36,7 @@ module Alchemy
|
|
|
36
36
|
else
|
|
37
37
|
uid = PictureThumb::Uid.call(signature, variant)
|
|
38
38
|
ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
|
|
39
|
-
PictureThumb.
|
|
39
|
+
PictureThumb::Create.call(variant, signature, uid)
|
|
40
40
|
end
|
|
41
41
|
uid
|
|
42
42
|
end
|
|
@@ -47,17 +47,16 @@ module Alchemy
|
|
|
47
47
|
include Alchemy::TouchElements
|
|
48
48
|
include Calculations
|
|
49
49
|
|
|
50
|
-
has_many :
|
|
51
|
-
class_name: "Alchemy::
|
|
52
|
-
foreign_key: "
|
|
53
|
-
inverse_of: :
|
|
50
|
+
has_many :picture_ingredients,
|
|
51
|
+
class_name: "Alchemy::Ingredients::Picture",
|
|
52
|
+
foreign_key: "related_object_id",
|
|
53
|
+
inverse_of: :related_object
|
|
54
54
|
|
|
55
|
-
has_many :
|
|
56
|
-
has_many :elements, through: :contents
|
|
55
|
+
has_many :elements, through: :picture_ingredients
|
|
57
56
|
has_many :pages, through: :elements
|
|
58
57
|
has_many :thumbs, class_name: "Alchemy::PictureThumb", dependent: :destroy
|
|
59
58
|
|
|
60
|
-
# Raise error, if picture is in use (aka. assigned to an
|
|
59
|
+
# Raise error, if picture is in use (aka. assigned to an Picture ingredient)
|
|
61
60
|
#
|
|
62
61
|
# === CAUTION
|
|
63
62
|
#
|
|
@@ -114,7 +113,10 @@ module Alchemy
|
|
|
114
113
|
|
|
115
114
|
scope :named, ->(name) { where("#{table_name}.name LIKE ?", "%#{name}%") }
|
|
116
115
|
scope :recent, -> { where("#{table_name}.created_at > ?", Time.current - 24.hours).order(:created_at) }
|
|
117
|
-
scope :deletable,
|
|
116
|
+
scope :deletable,
|
|
117
|
+
-> {
|
|
118
|
+
where("#{table_name}.id NOT IN (SELECT related_object_id FROM alchemy_ingredients WHERE related_object_type = 'Alchemy::Picture')")
|
|
119
|
+
}
|
|
118
120
|
scope :without_tag, -> { left_outer_joins(:taggings).where(gutentag_taggings: { id: nil }) }
|
|
119
121
|
scope :by_file_format, ->(format) { where(image_file_format: format) }
|
|
120
122
|
|
|
@@ -279,10 +281,10 @@ module Alchemy
|
|
|
279
281
|
pages.any? && pages.not_restricted.blank?
|
|
280
282
|
end
|
|
281
283
|
|
|
282
|
-
# Returns true if picture is not assigned to any
|
|
284
|
+
# Returns true if picture is not assigned to any Picture ingredient.
|
|
283
285
|
#
|
|
284
286
|
def deletable?
|
|
285
|
-
|
|
287
|
+
picture_ingredients.empty?
|
|
286
288
|
end
|
|
287
289
|
|
|
288
290
|
# A size String from original image file values.
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module Alchemy
|
|
4
4
|
class PictureThumb < BaseRecord
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# Creates a Alchemy::PictureThumb
|
|
6
|
+
#
|
|
7
|
+
# Stores the processes result of a Alchemy::PictureVariant
|
|
8
|
+
# in the configured +Alchemy::PictureThumb.storage_class+
|
|
9
|
+
# (Default: {Alchemy::PictureThumb::FileStore})
|
|
8
10
|
#
|
|
9
11
|
class Create
|
|
10
12
|
class << self
|
|
@@ -24,26 +26,13 @@ module Alchemy
|
|
|
24
26
|
thumb.uid = uid
|
|
25
27
|
end
|
|
26
28
|
begin
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# store the processed image
|
|
30
|
-
image.to_file(server_path(uid)).close
|
|
31
|
-
rescue RuntimeError => e
|
|
29
|
+
Alchemy::PictureThumb.storage_class.call(variant, uid)
|
|
30
|
+
rescue StandardError => e
|
|
32
31
|
ErrorTracking.notification_handler.call(e)
|
|
33
32
|
# destroy the thumb if processing or storing fails
|
|
34
33
|
@thumb&.destroy
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
# Alchemys dragonfly datastore config seperates the storage path from the public server
|
|
41
|
-
# path for security reasons. The Dragonfly FileDataStorage does not support that,
|
|
42
|
-
# so we need to build the path on our own.
|
|
43
|
-
def server_path(uid)
|
|
44
|
-
dragonfly_app = ::Dragonfly.app(:alchemy_pictures)
|
|
45
|
-
"#{dragonfly_app.datastore.server_root}/#{uid}"
|
|
46
|
-
end
|
|
47
36
|
end
|
|
48
37
|
end
|
|
49
38
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
class PictureThumb < BaseRecord
|
|
5
|
+
# Stores the render result of a Alchemy::PictureVariant
|
|
6
|
+
# in the configured Dragonfly datastore
|
|
7
|
+
# (Default: Dragonfly::FileDataStore)
|
|
8
|
+
#
|
|
9
|
+
class FileStore
|
|
10
|
+
class << self
|
|
11
|
+
# @param [Alchemy::PictureVariant] variant the to be rendered image
|
|
12
|
+
# @param [String] uid The Unique Image Identifier the image is stored at
|
|
13
|
+
#
|
|
14
|
+
def call(variant, uid)
|
|
15
|
+
# process the image
|
|
16
|
+
image = variant.image
|
|
17
|
+
# store the processed image
|
|
18
|
+
image.to_file(server_path(uid)).close
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# Alchemys dragonfly datastore config seperates the storage path from the public server
|
|
24
|
+
# path for security reasons. The Dragonfly FileDataStorage does not support that,
|
|
25
|
+
# so we need to build the path on our own.
|
|
26
|
+
def server_path(uid)
|
|
27
|
+
dragonfly_app = ::Dragonfly.app(:alchemy_pictures)
|
|
28
|
+
"#{dragonfly_app.datastore.server_root}/#{uid}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -7,7 +7,7 @@ module Alchemy
|
|
|
7
7
|
# different thumbnail store (ie. a remote file storage).
|
|
8
8
|
#
|
|
9
9
|
# config/initializers/alchemy.rb
|
|
10
|
-
# Alchemy::PictureThumb.
|
|
10
|
+
# Alchemy::PictureThumb.storage_class = My::ThumbnailStore
|
|
11
11
|
#
|
|
12
12
|
class PictureThumb < BaseRecord
|
|
13
13
|
belongs_to :picture, class_name: "Alchemy::Picture"
|
|
@@ -16,18 +16,18 @@ module Alchemy
|
|
|
16
16
|
validates :uid, presence: true
|
|
17
17
|
|
|
18
18
|
class << self
|
|
19
|
-
# Thumbnail
|
|
19
|
+
# Thumbnail storage class
|
|
20
20
|
#
|
|
21
|
-
# @see Alchemy::PictureThumb::
|
|
22
|
-
def
|
|
23
|
-
@
|
|
21
|
+
# @see Alchemy::PictureThumb::FileStore
|
|
22
|
+
def storage_class
|
|
23
|
+
@_storage_class ||= Alchemy::PictureThumb::FileStore
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
# Set a thumbnail
|
|
26
|
+
# Set a thumbnail storage class
|
|
27
27
|
#
|
|
28
|
-
# @see Alchemy::PictureThumb::
|
|
29
|
-
def
|
|
30
|
-
@
|
|
28
|
+
# @see Alchemy::PictureThumb::FileStore
|
|
29
|
+
def storage_class=(klass)
|
|
30
|
+
@_storage_class = klass
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Upfront generation of picture thumbnails
|
|
@@ -49,7 +49,7 @@ module Alchemy
|
|
|
49
49
|
next if thumb
|
|
50
50
|
|
|
51
51
|
uid = Alchemy::PictureThumb::Uid.call(signature, variant)
|
|
52
|
-
|
|
52
|
+
Alchemy::PictureThumb::Create.call(variant, signature, uid)
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|