alchemy_cms 5.2.4 → 6.0.0.b1
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 +6 -14
- data/.gitignore +0 -1
- data/.hound.yml +1 -1
- data/.rubocop.yml +46 -4
- data/CHANGELOG.md +80 -25
- data/Gemfile +4 -2
- data/README.md +5 -2
- data/alchemy_cms.gemspec +78 -65
- data/app/assets/javascripts/alchemy/admin.js +0 -2
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -27
- data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +2 -1
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +0 -25
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -0
- data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +1 -1
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
- data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +40 -27
- data/app/assets/javascripts/alchemy/templates/node_folder.hbs +1 -1
- data/app/assets/stylesheets/alchemy/admin.scss +1 -1
- data/app/assets/stylesheets/alchemy/archive.scss +4 -4
- data/app/assets/stylesheets/alchemy/buttons.scss +0 -4
- data/app/assets/stylesheets/alchemy/elements.scss +73 -61
- data/app/assets/stylesheets/alchemy/images.scss +8 -0
- data/app/assets/stylesheets/alchemy/node-select.scss +4 -3
- data/app/assets/stylesheets/alchemy/page-select.scss +1 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +6 -6
- data/app/controllers/alchemy/admin/attachments_controller.rb +6 -2
- data/app/controllers/alchemy/admin/base_controller.rb +5 -7
- data/app/controllers/alchemy/admin/elements_controller.rb +58 -34
- data/app/controllers/alchemy/admin/essence_audios_controller.rb +30 -0
- data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -14
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +8 -79
- data/app/controllers/alchemy/admin/essence_videos_controller.rb +33 -0
- data/app/controllers/alchemy/admin/ingredients_controller.rb +30 -0
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +0 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +6 -13
- data/app/controllers/alchemy/admin/pictures_controller.rb +35 -9
- data/app/controllers/alchemy/api/elements_controller.rb +10 -5
- data/app/controllers/alchemy/api/pages_controller.rb +2 -4
- data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +13 -3
- data/app/controllers/concerns/alchemy/admin/crop_action.rb +26 -0
- data/app/decorators/alchemy/element_editor.rb +23 -1
- data/app/decorators/alchemy/ingredient_editor.rb +154 -0
- data/app/helpers/alchemy/admin/elements_helper.rb +1 -0
- data/app/helpers/alchemy/admin/essences_helper.rb +1 -1
- data/app/helpers/alchemy/admin/ingredients_helper.rb +42 -0
- data/app/helpers/alchemy/elements_block_helper.rb +22 -7
- data/app/helpers/alchemy/elements_helper.rb +12 -5
- data/app/helpers/alchemy/pages_helper.rb +3 -11
- data/app/jobs/alchemy/base_job.rb +11 -0
- data/app/jobs/alchemy/publish_page_job.rb +11 -0
- data/app/models/alchemy/attachment.rb +1 -1
- data/app/models/alchemy/content/factory.rb +23 -27
- data/app/models/alchemy/content.rb +1 -6
- data/app/models/alchemy/element/definitions.rb +29 -27
- data/app/models/alchemy/element/element_contents.rb +131 -122
- data/app/models/alchemy/element/element_essences.rb +100 -98
- data/app/models/alchemy/element/element_ingredients.rb +176 -0
- data/app/models/alchemy/element/presenters.rb +89 -87
- data/app/models/alchemy/element.rb +40 -73
- data/app/models/alchemy/elements_repository.rb +126 -0
- data/app/models/alchemy/essence_audio.rb +12 -0
- data/app/models/alchemy/essence_headline.rb +40 -0
- data/app/models/alchemy/essence_picture.rb +4 -116
- data/app/models/alchemy/essence_richtext.rb +12 -0
- data/app/models/alchemy/essence_video.rb +12 -0
- data/app/models/alchemy/image_cropper_settings.rb +87 -0
- data/app/models/alchemy/ingredient.rb +219 -0
- data/app/models/alchemy/ingredient_validator.rb +97 -0
- data/app/models/alchemy/ingredients/audio.rb +29 -0
- data/app/models/alchemy/ingredients/boolean.rb +21 -0
- data/app/models/alchemy/ingredients/datetime.rb +20 -0
- data/app/models/alchemy/ingredients/file.rb +30 -0
- data/app/models/alchemy/ingredients/headline.rb +42 -0
- data/app/models/alchemy/ingredients/html.rb +19 -0
- data/app/models/alchemy/ingredients/link.rb +16 -0
- data/app/models/alchemy/ingredients/node.rb +23 -0
- data/app/models/alchemy/ingredients/page.rb +23 -0
- data/app/models/alchemy/ingredients/picture.rb +41 -0
- data/app/models/alchemy/ingredients/richtext.rb +57 -0
- data/app/models/alchemy/ingredients/select.rb +10 -0
- data/app/models/alchemy/ingredients/text.rb +17 -0
- data/app/models/alchemy/ingredients/video.rb +33 -0
- data/app/models/alchemy/language.rb +0 -11
- data/app/models/alchemy/node.rb +1 -1
- data/app/models/alchemy/page/fixed_attributes.rb +53 -51
- data/app/models/alchemy/page/page_elements.rb +186 -205
- data/app/models/alchemy/page/page_naming.rb +66 -64
- data/app/models/alchemy/page/page_natures.rb +139 -142
- data/app/models/alchemy/page/page_scopes.rb +113 -102
- data/app/models/alchemy/page/publisher.rb +50 -0
- data/app/models/alchemy/page/url_path.rb +1 -1
- data/app/models/alchemy/page.rb +67 -33
- data/app/models/alchemy/page_version.rb +58 -0
- data/app/models/alchemy/picture/calculations.rb +2 -8
- data/app/models/alchemy/picture/preprocessor.rb +2 -0
- data/app/models/alchemy/picture/transformations.rb +24 -96
- data/app/models/alchemy/picture.rb +4 -2
- data/app/models/concerns/alchemy/picture_thumbnails.rb +181 -0
- data/app/models/concerns/alchemy/touch_elements.rb +2 -2
- data/app/presenters/alchemy/picture_view.rb +88 -0
- data/app/serializers/alchemy/element_serializer.rb +5 -0
- data/app/serializers/alchemy/page_tree_serializer.rb +3 -2
- data/app/services/alchemy/delete_elements.rb +44 -0
- data/app/services/alchemy/duplicate_element.rb +56 -0
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
- data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +3 -3
- data/app/views/alchemy/admin/attachments/assign.js.erb +11 -0
- data/app/views/alchemy/admin/crop.html.erb +36 -0
- data/app/views/alchemy/admin/elements/_element.html.erb +14 -10
- data/app/views/alchemy/admin/elements/{_element_footer.html.erb → _footer.html.erb} +0 -0
- data/app/views/alchemy/admin/elements/{_new_element_form.html.erb → _form.html.erb} +1 -1
- data/app/views/alchemy/admin/elements/{_element_header.html.erb → _header.html.erb} +1 -1
- data/app/views/alchemy/admin/elements/{_element_toolbar.html.erb → _toolbar.html.erb} +5 -6
- data/app/views/alchemy/admin/elements/{trash.js.erb → destroy.js.erb} +1 -3
- data/app/views/alchemy/admin/elements/new.html.erb +3 -3
- data/app/views/alchemy/admin/elements/order.js.erb +0 -17
- data/app/views/alchemy/admin/elements/update.js.erb +3 -2
- data/app/views/alchemy/admin/essence_audios/edit.html.erb +7 -0
- data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -1
- data/app/views/alchemy/admin/essence_videos/edit.html.erb +11 -0
- data/app/views/alchemy/admin/ingredients/_audio_fields.html.erb +4 -0
- data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +18 -0
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +25 -0
- data/app/views/alchemy/admin/ingredients/_video_fields.html.erb +8 -0
- data/app/views/alchemy/admin/ingredients/edit.html.erb +4 -0
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +0 -5
- data/app/views/alchemy/admin/nodes/_node.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_anchor_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_external_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_file_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +0 -6
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +5 -2
- data/app/views/alchemy/admin/pages/edit.html.erb +36 -24
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +2 -4
- data/app/views/alchemy/admin/partials/_routes.html.erb +7 -11
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +4 -8
- data/app/views/alchemy/admin/pictures/_infos.html.erb +0 -1
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +4 -4
- data/app/views/alchemy/admin/pictures/assign.js.erb +10 -0
- data/app/views/alchemy/admin/resources/_form.html.erb +1 -0
- data/app/views/alchemy/essences/_essence_audio_editor.html.erb +4 -0
- data/app/views/alchemy/essences/_essence_audio_view.html.erb +15 -0
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +15 -6
- data/app/views/alchemy/essences/_essence_headline_editor.html.erb +36 -0
- data/app/views/alchemy/essences/_essence_headline_view.html.erb +10 -0
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +8 -4
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +27 -12
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +12 -4
- data/app/views/alchemy/essences/_essence_video_editor.html.erb +4 -0
- data/app/views/alchemy/essences/_essence_video_view.html.erb +18 -0
- data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +21 -16
- data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +2 -2
- data/app/views/alchemy/ingredients/_audio_editor.html.erb +5 -0
- data/app/views/alchemy/ingredients/_audio_view.html.erb +14 -0
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +11 -0
- data/app/views/alchemy/ingredients/_boolean_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_datetime_editor.html.erb +17 -0
- data/app/views/alchemy/ingredients/_datetime_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_file_editor.html.erb +50 -0
- data/app/views/alchemy/ingredients/_file_view.html.erb +17 -0
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +30 -0
- data/app/views/alchemy/ingredients/_headline_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_html_editor.html.erb +8 -0
- data/app/views/alchemy/ingredients/_html_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_link_editor.html.erb +24 -0
- data/app/views/alchemy/ingredients/_link_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_node_editor.html.erb +25 -0
- data/app/views/alchemy/ingredients/_node_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_page_editor.html.erb +24 -0
- data/app/views/alchemy/ingredients/_page_view.html.erb +4 -0
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +59 -0
- data/app/views/alchemy/ingredients/_picture_view.html.erb +5 -0
- data/app/views/alchemy/ingredients/_richtext_editor.html.erb +12 -0
- data/app/views/alchemy/ingredients/_richtext_view.html.erb +3 -0
- data/app/views/alchemy/ingredients/_select_editor.html.erb +29 -0
- data/app/views/alchemy/ingredients/_select_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_text_editor.html.erb +19 -0
- data/app/views/alchemy/ingredients/_text_view.html.erb +16 -0
- data/app/views/alchemy/ingredients/_video_editor.html.erb +5 -0
- data/app/views/alchemy/ingredients/_video_view.html.erb +17 -0
- data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +20 -0
- data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +57 -0
- data/config/brakeman.ignore +66 -159
- data/config/initializers/dragonfly.rb +10 -0
- data/config/locales/alchemy.en.yml +23 -15
- data/config/routes.rb +17 -22
- data/db/migrate/20201207131309_create_page_versions.rb +19 -0
- data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +76 -0
- data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +10 -0
- data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +7 -0
- data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +12 -0
- data/db/migrate/20210506135919_create_essence_audios.rb +19 -0
- data/db/migrate/20210506140258_create_essence_videos.rb +23 -0
- data/db/migrate/20210508091432_create_alchemy_ingredients.rb +22 -0
- data/lib/alchemy/admin/preview_url.rb +2 -0
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/dragonfly/processors/auto_orient.rb +18 -0
- data/lib/alchemy/dragonfly/processors/crop_resize.rb +35 -0
- data/lib/alchemy/elements_finder.rb +14 -60
- data/lib/alchemy/engine.rb +1 -1
- data/lib/alchemy/essence.rb +1 -2
- data/lib/alchemy/hints.rb +8 -4
- data/lib/alchemy/page_layout.rb +0 -13
- data/lib/alchemy/permissions.rb +30 -29
- data/lib/alchemy/resource.rb +13 -3
- data/lib/alchemy/tasks/tidy.rb +29 -0
- data/lib/alchemy/test_support/essence_shared_examples.rb +0 -1
- data/lib/alchemy/test_support/factories/element_factory.rb +8 -8
- data/lib/alchemy/test_support/factories/essence_audio_factory.rb +7 -0
- data/lib/alchemy/test_support/factories/essence_video_factory.rb +7 -0
- data/lib/alchemy/test_support/factories/ingredient_factory.rb +25 -0
- data/lib/alchemy/test_support/factories/page_factory.rb +20 -1
- data/lib/alchemy/test_support/factories/page_version_factory.rb +23 -0
- data/lib/alchemy/test_support/having_crop_action_examples.rb +170 -0
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +646 -0
- data/lib/alchemy/test_support/shared_ingredient_editor_examples.rb +21 -0
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +57 -0
- data/lib/alchemy/test_support.rb +2 -11
- data/lib/alchemy/tinymce.rb +17 -0
- data/lib/alchemy/upgrader/five_point_zero.rb +0 -32
- data/lib/alchemy/upgrader/six_point_zero.rb +21 -0
- data/lib/alchemy/upgrader/tasks/add_page_versions.rb +33 -0
- data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +51 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/generators/alchemy/elements/elements_generator.rb +1 -0
- data/lib/generators/alchemy/elements/templates/view.html.erb +9 -0
- data/lib/generators/alchemy/elements/templates/view.html.haml +9 -0
- data/lib/generators/alchemy/elements/templates/view.html.slim +9 -0
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +38 -0
- data/lib/generators/alchemy/ingredient/templates/editor.html.erb +14 -0
- data/lib/generators/alchemy/ingredient/templates/model.rb.tt +13 -0
- data/lib/generators/alchemy/ingredient/templates/view.html.erb +1 -0
- data/lib/generators/alchemy/install/install_generator.rb +1 -2
- data/lib/generators/alchemy/install/templates/dragonfly.rb.tt +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.erb +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.haml +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.slim +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.erb +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.haml +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.slim +1 -1
- data/lib/tasks/alchemy/tidy.rake +12 -0
- data/lib/tasks/alchemy/upgrade.rake +21 -15
- data/package/admin.js +9 -1
- data/package/src/file_editors.js +28 -0
- data/package/src/image_cropper.js +103 -0
- data/package/src/image_loader.js +58 -0
- data/package/src/node_tree.js +5 -5
- data/package/src/picture_editors.js +169 -0
- data/package/src/utils/__tests__/ajax.spec.js +20 -12
- data/package/src/utils/ajax.js +8 -3
- data/package.json +3 -2
- data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +3 -18
- data/vendor/assets/stylesheets/jquery.Jcrop.min.scss +2 -28
- metadata +285 -56
- data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +0 -44
- data/app/assets/javascripts/alchemy/alchemy.trash_window.js.coffee +0 -30
- data/app/assets/stylesheets/alchemy/trash.scss +0 -8
- data/app/controllers/alchemy/admin/trash_controller.rb +0 -44
- data/app/views/alchemy/admin/essence_files/assign.js.erb +0 -3
- data/app/views/alchemy/admin/essence_pictures/assign.js.erb +0 -4
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +0 -48
- data/app/views/alchemy/admin/trash/clear.js.erb +0 -4
- data/app/views/alchemy/admin/trash/index.html.erb +0 -31
- data/lib/alchemy/test_support/factories.rb +0 -20
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A text headline
|
|
6
|
+
#
|
|
7
|
+
class Headline < Alchemy::Ingredient
|
|
8
|
+
store_accessor :data,
|
|
9
|
+
:level,
|
|
10
|
+
:size
|
|
11
|
+
|
|
12
|
+
before_create :set_level_and_size
|
|
13
|
+
|
|
14
|
+
def preview_text(maxlength = 30)
|
|
15
|
+
"H#{level}: #{value}"[0..maxlength - 1]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def level_options
|
|
19
|
+
levels.map { |level| ["H#{level}", level] }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def size_options
|
|
23
|
+
sizes.map { |size| ["H#{size}", size] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def levels
|
|
29
|
+
settings.fetch(:levels, (1..6))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def sizes
|
|
33
|
+
settings.fetch(:sizes, [])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def set_level_and_size
|
|
37
|
+
self.level ||= levels.first
|
|
38
|
+
self.size ||= sizes.first
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A HTML string
|
|
6
|
+
#
|
|
7
|
+
class Html < Alchemy::Ingredient
|
|
8
|
+
# The first 30 escaped characters from value
|
|
9
|
+
#
|
|
10
|
+
# Used by the Element#preview_text method.
|
|
11
|
+
#
|
|
12
|
+
# @param [Integer] max_length (30)
|
|
13
|
+
#
|
|
14
|
+
def preview_text(max_length = 30)
|
|
15
|
+
::CGI.escapeHTML(value.to_s)[0..max_length - 1]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A link to a menu node
|
|
6
|
+
#
|
|
7
|
+
# Assign Alchemy::Node to this ingredient
|
|
8
|
+
#
|
|
9
|
+
class Node < Alchemy::Ingredient
|
|
10
|
+
related_object_alias :node, class_name: "Alchemy::Node"
|
|
11
|
+
|
|
12
|
+
# The first 30 characters of node name
|
|
13
|
+
#
|
|
14
|
+
# Used by the Element#preview_text method.
|
|
15
|
+
#
|
|
16
|
+
# @param [Integer] max_length (30)
|
|
17
|
+
#
|
|
18
|
+
def preview_text(max_length = 30)
|
|
19
|
+
node&.name.to_s[0..max_length - 1]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A link to a page
|
|
6
|
+
#
|
|
7
|
+
# Assign Alchemy::Page to this ingredient
|
|
8
|
+
#
|
|
9
|
+
class Page < Alchemy::Ingredient
|
|
10
|
+
related_object_alias :page, class_name: "Alchemy::Page"
|
|
11
|
+
|
|
12
|
+
# The first 30 characters of page name
|
|
13
|
+
#
|
|
14
|
+
# Used by the Element#preview_text method.
|
|
15
|
+
#
|
|
16
|
+
# @param [Integer] max_length (30)
|
|
17
|
+
#
|
|
18
|
+
def preview_text(max_length = 30)
|
|
19
|
+
page&.name.to_s[0..max_length - 1]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A picture assignment
|
|
6
|
+
#
|
|
7
|
+
# Assign Alchemy::Picture to this ingredient
|
|
8
|
+
#
|
|
9
|
+
# Optionally you can add a link
|
|
10
|
+
# As well as set the alt tag, a caption and title
|
|
11
|
+
#
|
|
12
|
+
class Picture < Alchemy::Ingredient
|
|
13
|
+
include Alchemy::PictureThumbnails
|
|
14
|
+
|
|
15
|
+
store_accessor :data,
|
|
16
|
+
:alt_tag,
|
|
17
|
+
:caption,
|
|
18
|
+
:crop_from,
|
|
19
|
+
:crop_size,
|
|
20
|
+
:css_class,
|
|
21
|
+
:link_class_name,
|
|
22
|
+
:link_target,
|
|
23
|
+
:link_title,
|
|
24
|
+
:link,
|
|
25
|
+
:render_size,
|
|
26
|
+
:title
|
|
27
|
+
|
|
28
|
+
related_object_alias :picture, class_name: "Alchemy::Picture"
|
|
29
|
+
|
|
30
|
+
# The first 30 characters of the pictures name
|
|
31
|
+
#
|
|
32
|
+
# Used by the Element#preview_text method.
|
|
33
|
+
#
|
|
34
|
+
# @param [Integer] max_length (30)
|
|
35
|
+
#
|
|
36
|
+
def preview_text(max_length = 30)
|
|
37
|
+
picture&.name.to_s[0..max_length - 1]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A blob of richtext
|
|
6
|
+
#
|
|
7
|
+
class Richtext < Alchemy::Ingredient
|
|
8
|
+
store_accessor :data,
|
|
9
|
+
:stripped_body,
|
|
10
|
+
:sanitized_body
|
|
11
|
+
|
|
12
|
+
before_save :strip_content
|
|
13
|
+
before_save :sanitize_content
|
|
14
|
+
|
|
15
|
+
# The first 30 characters of the stripped_body
|
|
16
|
+
#
|
|
17
|
+
# Used by the Element#preview_text method.
|
|
18
|
+
#
|
|
19
|
+
# @param [Integer] max_length (30)
|
|
20
|
+
#
|
|
21
|
+
def preview_text(max_length = 30)
|
|
22
|
+
stripped_body.to_s[0..max_length - 1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns css class names for the editor textarea.
|
|
26
|
+
def tinymce_class_name
|
|
27
|
+
"has_tinymce#{has_custom_tinymce_config? ? " #{element.name}_#{role}" : ""}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def has_tinymce?
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def strip_content
|
|
37
|
+
self.stripped_body = Rails::Html::FullSanitizer.new.sanitize(value)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def sanitize_content
|
|
41
|
+
self.sanitized_body = Rails::Html::SafeListSanitizer.new.sanitize(
|
|
42
|
+
value,
|
|
43
|
+
sanitizer_settings
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def sanitizer_settings
|
|
48
|
+
settings[:sanitizer] || {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns true if there is a tinymce setting defined that contains settings.
|
|
52
|
+
def has_custom_tinymce_config?
|
|
53
|
+
settings[:tinymce].is_a?(Hash)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A simple line of text
|
|
6
|
+
#
|
|
7
|
+
# Optionally it can have a link
|
|
8
|
+
#
|
|
9
|
+
class Text < Alchemy::Ingredient
|
|
10
|
+
store_accessor :data,
|
|
11
|
+
:link,
|
|
12
|
+
:link_target,
|
|
13
|
+
:link_title,
|
|
14
|
+
:link_class_name
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Ingredients
|
|
5
|
+
# A video attachment
|
|
6
|
+
#
|
|
7
|
+
class Video < Alchemy::Ingredient
|
|
8
|
+
store_accessor :data,
|
|
9
|
+
:allow_fullscreen,
|
|
10
|
+
:autoplay,
|
|
11
|
+
:controls,
|
|
12
|
+
:height,
|
|
13
|
+
:loop,
|
|
14
|
+
:muted,
|
|
15
|
+
:preload,
|
|
16
|
+
:width
|
|
17
|
+
|
|
18
|
+
related_object_alias :attachment, class_name: "Alchemy::Attachment"
|
|
19
|
+
|
|
20
|
+
delegate :name, to: :attachment, allow_nil: true
|
|
21
|
+
|
|
22
|
+
# The first 30 characters of the attachments name
|
|
23
|
+
#
|
|
24
|
+
# Used by the Element#preview_text method.
|
|
25
|
+
#
|
|
26
|
+
# @param [Integer] max_length (30)
|
|
27
|
+
#
|
|
28
|
+
def preview_text(max_length = 30)
|
|
29
|
+
name.to_s[0..max_length - 1]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -54,9 +54,6 @@ module Alchemy
|
|
|
54
54
|
after_update :set_pages_language,
|
|
55
55
|
if: :should_set_pages_language?
|
|
56
56
|
|
|
57
|
-
after_update :unpublish_pages,
|
|
58
|
-
if: :should_unpublish_pages?
|
|
59
|
-
|
|
60
57
|
before_destroy if: -> { pages.any? } do
|
|
61
58
|
errors.add(:pages, :still_present)
|
|
62
59
|
throw(:abort)
|
|
@@ -170,13 +167,5 @@ module Alchemy
|
|
|
170
167
|
def set_pages_language
|
|
171
168
|
pages.update_all language_code: code
|
|
172
169
|
end
|
|
173
|
-
|
|
174
|
-
def should_unpublish_pages?
|
|
175
|
-
saved_changes[:public] == [true, false]
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
def unpublish_pages
|
|
179
|
-
pages.update_all(public_on: nil, public_until: nil)
|
|
180
|
-
end
|
|
181
170
|
end
|
|
182
171
|
end
|
data/app/models/alchemy/node.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Alchemy
|
|
|
7
7
|
before_destroy :check_if_related_essence_nodes_present
|
|
8
8
|
|
|
9
9
|
acts_as_nested_set scope: "language_id", touch: true
|
|
10
|
-
stampable stamper_class_name: Alchemy.
|
|
10
|
+
stampable stamper_class_name: Alchemy.user_class_name
|
|
11
11
|
|
|
12
12
|
belongs_to :language, class_name: "Alchemy::Language"
|
|
13
13
|
belongs_to :page, class_name: "Alchemy::Page", optional: true, inverse_of: :nodes
|
|
@@ -1,66 +1,68 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Alchemy
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# Fixed page attributes are not allowed to be changed by the user.
|
|
7
|
-
#
|
|
8
|
-
# Define fixed page attributes on the page layout definition of a page.
|
|
9
|
-
#
|
|
10
|
-
# == Example
|
|
11
|
-
#
|
|
12
|
-
# # page_layout.yml
|
|
13
|
-
# - name: Index
|
|
14
|
-
# unique: true
|
|
15
|
-
# fixed_attributes:
|
|
16
|
-
# - public_on: nil
|
|
17
|
-
# - public_until: nil
|
|
18
|
-
#
|
|
19
|
-
class Page::FixedAttributes
|
|
20
|
-
attr_reader :page
|
|
21
|
-
|
|
22
|
-
def initialize(page)
|
|
23
|
-
@page = page
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# All fixed attributes defined on page
|
|
4
|
+
class Page < BaseRecord
|
|
5
|
+
# = Fixed page attributes
|
|
27
6
|
#
|
|
28
|
-
#
|
|
7
|
+
# Fixed page attributes are not allowed to be changed by the user.
|
|
29
8
|
#
|
|
30
|
-
#
|
|
9
|
+
# Define fixed page attributes on the page layout definition of a page.
|
|
31
10
|
#
|
|
32
|
-
|
|
33
|
-
@_attributes ||= page.definition.fetch("fixed_attributes", {}).symbolize_keys
|
|
34
|
-
end
|
|
35
|
-
alias_method :all, :attributes
|
|
36
|
-
|
|
37
|
-
# True if fixed attributes are defined on page
|
|
38
|
-
#
|
|
39
|
-
# Aliased as +#present?+
|
|
11
|
+
# == Example
|
|
40
12
|
#
|
|
41
|
-
#
|
|
13
|
+
# # page_layout.yml
|
|
14
|
+
# - name: Index
|
|
15
|
+
# unique: true
|
|
16
|
+
# fixed_attributes:
|
|
17
|
+
# - public_on: nil
|
|
18
|
+
# - public_until: nil
|
|
42
19
|
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
alias_method :present?, :any?
|
|
20
|
+
class FixedAttributes
|
|
21
|
+
attr_reader :page
|
|
47
22
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
def fixed?(name)
|
|
53
|
-
return false if name.nil?
|
|
23
|
+
def initialize(page)
|
|
24
|
+
@page = page
|
|
25
|
+
end
|
|
54
26
|
|
|
55
|
-
attributes
|
|
56
|
-
|
|
27
|
+
# All fixed attributes defined on page
|
|
28
|
+
#
|
|
29
|
+
# Aliased as +#all+
|
|
30
|
+
#
|
|
31
|
+
# @return Hash
|
|
32
|
+
#
|
|
33
|
+
def attributes
|
|
34
|
+
@_attributes ||= page.definition.fetch("fixed_attributes", {}).symbolize_keys
|
|
35
|
+
end
|
|
36
|
+
alias_method :all, :attributes
|
|
57
37
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
38
|
+
# True if fixed attributes are defined on page
|
|
39
|
+
#
|
|
40
|
+
# Aliased as +#present?+
|
|
41
|
+
#
|
|
42
|
+
# @return Boolean
|
|
43
|
+
#
|
|
44
|
+
def any?
|
|
45
|
+
attributes.present?
|
|
46
|
+
end
|
|
47
|
+
alias_method :present?, :any?
|
|
48
|
+
|
|
49
|
+
# True if given attribute name is defined on page
|
|
50
|
+
#
|
|
51
|
+
# @return Boolean
|
|
52
|
+
#
|
|
53
|
+
def fixed?(name)
|
|
54
|
+
return false if name.nil?
|
|
55
|
+
|
|
56
|
+
attributes.key?(name.to_sym)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns the attribute by key
|
|
60
|
+
#
|
|
61
|
+
def [](name)
|
|
62
|
+
return nil if name.nil?
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
attributes[name.to_sym]
|
|
65
|
+
end
|
|
64
66
|
end
|
|
65
67
|
end
|
|
66
68
|
end
|