alchemy_cms 7.4.10 → 8.0.0.b
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.
Potentially problematic release.
This version of alchemy_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +16 -5
- data/app/assets/builds/alchemy/admin/page-select.css +1 -1
- data/app/assets/builds/alchemy/admin/print.css +1 -1
- data/app/assets/builds/alchemy/admin.css +2 -2
- data/app/assets/builds/alchemy/dark-theme.css +1 -0
- data/app/assets/builds/alchemy/light-theme.css +1 -0
- data/app/assets/builds/alchemy/theme.css +1 -0
- data/app/assets/builds/alchemy/welcome.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy-dark/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -1
- data/app/assets/builds/tinymce/skins/ui/alchemy-dark/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy-dark/skin.min.css +1 -0
- data/app/assets/config/alchemy_manifest.js +0 -2
- data/app/assets/images/alchemy/element_icons/default.svg +1 -0
- data/app/assets/images/alchemy/icons-sprite.svg +1 -0
- data/app/components/alchemy/admin/element_select.rb +39 -0
- data/app/components/alchemy/admin/resource/applied_filter.rb +29 -0
- data/app/components/alchemy/admin/resource/checkbox_filter.rb +36 -0
- data/app/components/alchemy/admin/resource/datepicker_filter.rb +42 -0
- data/app/components/alchemy/admin/resource/select_filter.rb +43 -0
- data/app/components/alchemy/admin/toolbar_button.rb +5 -2
- data/app/components/alchemy/ingredients/number_view.rb +18 -0
- data/app/controllers/alchemy/admin/attachments_controller.rb +10 -15
- data/app/controllers/alchemy/admin/clipboard_controller.rb +2 -6
- data/app/controllers/alchemy/admin/elements_controller.rb +3 -1
- data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +15 -15
- data/app/controllers/alchemy/admin/pictures_controller.rb +27 -37
- data/app/controllers/alchemy/admin/resources_controller.rb +16 -106
- data/app/controllers/alchemy/attachments_controller.rb +43 -14
- data/app/controllers/alchemy/messages_controller.rb +1 -1
- data/app/controllers/alchemy/pages_controller.rb +26 -4
- data/app/controllers/concerns/alchemy/admin/resource_filter.rb +93 -0
- data/app/decorators/alchemy/element_editor.rb +5 -48
- data/app/decorators/alchemy/ingredient_editor.rb +3 -53
- data/app/helpers/alchemy/admin/attachments_helper.rb +5 -5
- data/app/helpers/alchemy/admin/base_helper.rb +14 -84
- data/app/helpers/alchemy/admin/pages_helper.rb +1 -1
- data/app/helpers/alchemy/base_helper.rb +0 -30
- data/app/helpers/alchemy/elements_block_helper.rb +0 -14
- data/app/helpers/alchemy/pages_helper.rb +1 -1
- data/{lib → app/helpers}/alchemy/resources_helper.rb +5 -45
- data/app/javascript/alchemy_admin/components/action.js +2 -0
- data/app/javascript/alchemy_admin/components/alchemy_html_element.js +3 -3
- data/app/javascript/alchemy_admin/components/auto_submit.js +20 -0
- data/app/javascript/alchemy_admin/components/datepicker.js +18 -7
- data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +8 -7
- data/app/javascript/alchemy_admin/components/element_editor.js +25 -15
- data/app/javascript/alchemy_admin/components/element_select.js +43 -0
- data/app/javascript/alchemy_admin/components/index.js +3 -0
- data/app/javascript/alchemy_admin/components/link_buttons.js +6 -2
- data/app/javascript/alchemy_admin/components/remote_select.js +9 -2
- data/app/javascript/alchemy_admin/components/tags_autocomplete.js +5 -1
- data/app/javascript/alchemy_admin/components/tinymce.js +93 -14
- data/app/javascript/alchemy_admin/components/update_check.js +42 -0
- data/app/javascript/alchemy_admin/components/uploader/file_upload.js +15 -8
- data/app/javascript/alchemy_admin/components/uploader/progress.js +12 -6
- data/app/javascript/alchemy_admin/components/uploader.js +4 -2
- data/app/javascript/alchemy_admin/confirm_dialog.js +27 -57
- data/app/javascript/alchemy_admin/dialog.js +1 -1
- data/app/javascript/alchemy_admin/dirty.js +3 -2
- data/app/javascript/alchemy_admin/file_editors.js +1 -1
- data/app/javascript/alchemy_admin/i18n.js +15 -16
- data/app/javascript/alchemy_admin/image_loader.js +4 -2
- data/app/javascript/alchemy_admin/initializer.js +1 -49
- data/app/javascript/alchemy_admin/picture_editors.js +7 -4
- data/app/javascript/alchemy_admin/picture_selector.js +4 -4
- data/app/javascript/alchemy_admin/utils/ajax.js +51 -44
- data/app/javascript/alchemy_admin.js +3 -8
- data/app/jobs/alchemy/delete_picture_job.rb +12 -0
- data/app/models/alchemy/admin/filters/base.rb +38 -0
- data/app/models/alchemy/admin/filters/checkbox.rb +24 -0
- data/app/models/alchemy/admin/filters/datepicker.rb +53 -0
- data/app/models/alchemy/admin/filters/select.rb +70 -0
- data/app/models/alchemy/admin/resource_name.rb +27 -0
- data/app/models/alchemy/attachment.rb +49 -44
- data/app/models/alchemy/base_record.rb +2 -0
- data/app/models/alchemy/element/definitions.rb +1 -1
- data/app/models/alchemy/element/element_ingredients.rb +6 -6
- data/app/models/alchemy/element/presenters.rb +3 -12
- data/app/models/alchemy/element.rb +10 -27
- data/app/models/alchemy/element_definition.rb +190 -0
- data/app/models/alchemy/ingredient.rb +10 -43
- data/app/models/alchemy/ingredient_definition.rb +134 -0
- data/app/models/alchemy/ingredient_validator.rb +7 -3
- data/app/models/alchemy/ingredients/number.rb +19 -0
- data/app/models/alchemy/language.rb +2 -21
- data/app/models/alchemy/message.rb +3 -7
- data/app/models/alchemy/node.rb +1 -1
- data/app/models/alchemy/page/{page_layouts.rb → definitions.rb} +12 -19
- data/app/models/alchemy/page/fixed_attributes.rb +1 -1
- data/app/models/alchemy/page/page_elements.rb +13 -14
- data/app/models/alchemy/page/page_naming.rb +3 -11
- data/app/models/alchemy/page/page_natures.rb +20 -15
- data/app/models/alchemy/page/page_scopes.rb +1 -1
- data/app/models/alchemy/page.rb +12 -39
- data/app/models/alchemy/page_definition.rb +115 -0
- data/app/models/alchemy/picture.rb +71 -99
- data/app/models/alchemy/picture_variant.rb +115 -5
- data/{lib → app/models}/alchemy/resource.rb +4 -18
- data/{lib → app/models}/alchemy/searchable_resource.rb +15 -0
- data/app/models/alchemy/site/layout.rb +5 -5
- data/app/models/alchemy/site.rb +1 -21
- data/app/models/alchemy/storage_adapter/active_storage/attachment_url.rb +41 -0
- data/app/models/alchemy/storage_adapter/active_storage/picture_url.rb +55 -0
- data/app/models/alchemy/storage_adapter/active_storage/preprocessor.rb +40 -0
- data/app/models/alchemy/storage_adapter/active_storage.rb +173 -0
- data/app/models/alchemy/{attachment/url.rb → storage_adapter/dragonfly/attachment_url.rb} +12 -12
- data/app/models/alchemy/storage_adapter/dragonfly/picture_url.rb +75 -0
- data/app/models/alchemy/{picture → storage_adapter/dragonfly}/preprocessor.rb +4 -4
- data/app/models/alchemy/storage_adapter/dragonfly.rb +205 -0
- data/app/models/alchemy/storage_adapter.rb +74 -0
- data/app/models/concerns/alchemy/picture_thumbnails.rb +19 -6
- data/app/models/concerns/alchemy/relatable_resource.rb +28 -0
- data/app/serializers/alchemy/element_serializer.rb +0 -1
- data/app/services/alchemy/dragonfly_to_image_processing.rb +100 -0
- data/app/stylesheets/alchemy/_custom-properties.scss +162 -0
- data/app/stylesheets/alchemy/_defaults.scss +3 -0
- data/app/stylesheets/alchemy/_extends.scss +69 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/_mixins.scss +40 -68
- data/app/stylesheets/alchemy/_themes.scss +540 -0
- data/app/stylesheets/alchemy/_variables.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/archive.scss +45 -42
- data/app/stylesheets/alchemy/admin/attachments.scss +17 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/base.scss +20 -15
- data/app/stylesheets/alchemy/admin/buttons.scss +135 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/clipboard.scss +2 -2
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/dashboard.scss +13 -16
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/dialogs.scss +33 -16
- data/app/stylesheets/alchemy/admin/element-select.scss +11 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/elements.scss +239 -133
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/errors.scss +5 -5
- data/app/stylesheets/alchemy/admin/filters.scss +57 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/flatpickr.scss +54 -76
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/form_fields.scss +10 -11
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/forms.scss +28 -21
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/frame.scss +20 -18
- data/app/stylesheets/alchemy/admin/hints.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/icons.scss +1 -1
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/image_library.scss +21 -61
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/images.scss +1 -1
- data/app/stylesheets/alchemy/admin/labels.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/lists.scss +3 -3
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/navigation.scss +55 -59
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/node-select.scss +1 -10
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/nodes.scss +21 -18
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/notices.scss +20 -19
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/page-select.scss +18 -2
- data/app/stylesheets/alchemy/admin/pagination.scss +137 -0
- data/app/stylesheets/alchemy/admin/preview_window.scss +46 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/print.scss +1 -1
- data/app/stylesheets/alchemy/admin/resource_info.scss +148 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/search.scss +10 -7
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/selects.scss +85 -46
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/shoelace.scss +37 -68
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/sitemap.scss +39 -34
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/tables.scss +9 -7
- data/app/stylesheets/alchemy/admin/tags.scss +143 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/toolbar.scss +6 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/typography.scss +3 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/upload.scss +7 -5
- data/app/stylesheets/alchemy/admin.scss +44 -0
- data/app/stylesheets/alchemy/dark-theme.scss +5 -0
- data/app/stylesheets/alchemy/light-theme.scss +6 -0
- data/app/stylesheets/alchemy/theme.scss +13 -0
- data/app/stylesheets/alchemy/welcome.scss +75 -0
- data/app/stylesheets/tinymce/skins/content/alchemy/content.scss +69 -0
- data/app/{assets/stylesheets/tinymce/skins/content/alchemy → stylesheets/tinymce/skins/content/alchemy-dark}/content.scss +12 -12
- data/app/stylesheets/tinymce/skins/ui/alchemy/content.scss +1 -0
- data/app/{assets/stylesheets → stylesheets}/tinymce/skins/ui/alchemy/skin.scss +158 -176
- data/app/stylesheets/tinymce/skins/ui/alchemy-dark/content.scss +1 -0
- data/app/stylesheets/tinymce/skins/ui/alchemy-dark/skin.scss +3784 -0
- data/app/views/alchemy/admin/attachments/_files_list.html.erb +22 -12
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/assign.js.erb +4 -3
- data/app/views/alchemy/admin/attachments/show.html.erb +55 -43
- data/app/views/alchemy/admin/{elements/_clipboard_button.html.erb → clipboard/_button.html.erb} +3 -5
- data/app/views/alchemy/admin/clipboard/_update_nested_element_button.turbo_stream.erb +11 -0
- data/app/views/alchemy/admin/clipboard/clear.turbo_stream.erb +4 -0
- data/app/views/alchemy/admin/clipboard/index.html.erb +15 -13
- data/app/views/alchemy/admin/clipboard/insert.turbo_stream.erb +18 -0
- data/app/views/alchemy/admin/clipboard/remove.turbo_stream.erb +9 -0
- data/app/views/alchemy/admin/crop.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/info.html.erb +17 -31
- data/app/views/alchemy/admin/elements/_element.html.erb +4 -8
- data/app/views/alchemy/admin/elements/_form.html.erb +9 -9
- data/app/views/alchemy/admin/elements/_header.html.erb +5 -1
- data/app/views/alchemy/admin/elements/_toolbar.html.erb +4 -6
- data/app/views/alchemy/admin/elements/create.turbo_stream.erb +2 -1
- data/app/views/alchemy/admin/elements/index.html.erb +2 -2
- data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +3 -16
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +0 -9
- data/app/views/alchemy/admin/languages/_form.html.erb +1 -1
- data/app/views/alchemy/admin/languages/_table.html.erb +1 -1
- data/app/views/alchemy/admin/languages/index.html.erb +5 -2
- data/app/views/alchemy/admin/layoutpages/index.html.erb +1 -12
- data/app/views/alchemy/admin/pages/_form.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_page.html.erb +2 -3
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +1 -15
- data/app/views/alchemy/admin/pages/index.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +9 -12
- data/app/views/alchemy/admin/partials/_search_form.html.erb +4 -9
- data/app/views/alchemy/admin/pictures/_archive.html.erb +16 -29
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +3 -7
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_infos.html.erb +21 -52
- data/app/views/alchemy/admin/pictures/_library_sidebar.html.erb +7 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +14 -20
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +20 -16
- data/app/views/alchemy/admin/pictures/_sorting_select.html.erb +13 -0
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +1 -6
- data/app/views/alchemy/admin/pictures/index.html.erb +5 -19
- data/app/views/alchemy/admin/pictures/show.html.erb +10 -5
- data/app/views/alchemy/admin/resources/_applied_filters.html.erb +8 -0
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +5 -25
- data/app/views/alchemy/admin/resources/_pagination.html.erb +6 -0
- data/app/views/alchemy/admin/resources/_per_page_select.html.erb +4 -2
- data/app/views/alchemy/admin/resources/_resource_table.html.erb +1 -1
- data/app/views/alchemy/admin/resources/_resource_usage_info.html.erb +36 -0
- data/app/views/alchemy/admin/resources/_table_header.html.erb +1 -15
- data/app/views/alchemy/admin/sites/index.html.erb +5 -1
- data/app/views/alchemy/admin/styleguide/index.html.erb +118 -58
- data/app/views/alchemy/admin/tags/index.html.erb +1 -1
- data/app/views/alchemy/admin/tinymce/_setup.html.erb +7 -7
- data/app/{javascript/alchemy_admin/locales/en.js → views/alchemy/admin/translations/_en.js} +5 -2
- data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
- data/app/views/alchemy/admin/uploader/_setup.html.erb +4 -4
- data/app/views/alchemy/base/error_notice.html.erb +1 -1
- data/app/views/alchemy/ingredients/_number_editor.html.erb +24 -0
- data/app/views/alchemy/no_index.html.erb +31 -0
- data/app/views/alchemy/welcome.html.erb +12 -10
- data/app/views/kaminari/alchemy/_first_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_last_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_next_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_paginator.html.erb +18 -13
- data/app/views/kaminari/alchemy/_prev_page.html.erb +5 -3
- data/app/views/layouts/alchemy/admin.html.erb +25 -24
- data/config/alchemy/config.yml +3 -2
- data/config/initializers/dragonfly.rb +0 -1
- data/config/initializers/mime_types.rb +1 -0
- data/config/locales/alchemy.en.yml +57 -21
- data/config/routes.rb +0 -2
- data/db/migrate/20250905140323_add_created_at_index_to_pictures_and_attachments.rb +14 -0
- data/lib/alchemy/admin/preview_url.rb +4 -5
- data/lib/alchemy/cache_digests/template_tracker.rb +6 -9
- data/lib/alchemy/config_missing.rb +14 -0
- data/lib/alchemy/configuration/base_option.rb +24 -0
- data/lib/alchemy/configuration/boolean_option.rb +16 -0
- data/lib/alchemy/configuration/class_option.rb +15 -0
- data/lib/alchemy/configuration/class_set_option.rb +46 -0
- data/lib/alchemy/configuration/integer_list_option.rb +13 -0
- data/lib/alchemy/configuration/integer_option.rb +12 -0
- data/lib/alchemy/configuration/list_option.rb +22 -0
- data/lib/alchemy/configuration/regexp_option.rb +11 -0
- data/lib/alchemy/configuration/string_list_option.rb +13 -0
- data/lib/alchemy/configuration/string_option.rb +11 -0
- data/lib/alchemy/configuration.rb +115 -0
- data/lib/alchemy/configuration_methods.rb +3 -1
- data/lib/alchemy/configurations/default_language.rb +12 -0
- data/lib/alchemy/configurations/default_site.rb +10 -0
- data/lib/alchemy/configurations/format_matchers.rb +11 -0
- data/lib/alchemy/configurations/mailer.rb +16 -0
- data/lib/alchemy/configurations/main.rb +223 -0
- data/lib/alchemy/configurations/page_cache.rb +19 -0
- data/lib/alchemy/configurations/preview.rb +32 -0
- data/lib/alchemy/configurations/sitemap.rb +10 -0
- data/lib/alchemy/configurations/uploader.rb +34 -0
- data/lib/alchemy/engine.rb +81 -24
- data/lib/alchemy/hints.rb +3 -7
- data/lib/alchemy/install/tasks.rb +0 -12
- data/lib/alchemy/on_page_layout.rb +2 -2
- data/lib/alchemy/propshaft/tinymce_asset.rb +15 -0
- data/lib/alchemy/seeder.rb +2 -2
- data/lib/alchemy/tasks/tidy.rb +18 -0
- data/lib/alchemy/tasks/usage.rb +4 -4
- data/lib/alchemy/test_support/config_stubbing.rb +1 -7
- data/lib/alchemy/test_support/factories/attachment_factory.rb +13 -2
- data/lib/alchemy/test_support/factories/language_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/page_factory.rb +2 -3
- data/lib/alchemy/test_support/factories/picture_factory.rb +31 -2
- data/lib/alchemy/test_support/factories/site_factory.rb +2 -2
- data/lib/alchemy/test_support/having_crop_action_examples.rb +2 -2
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +80 -26
- data/lib/alchemy/test_support/relatable_resource_examples.rb +58 -0
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +5 -5
- data/lib/alchemy/tinymce.rb +0 -1
- data/lib/alchemy/upgrader/eight_zero.rb +14 -0
- data/lib/alchemy/upgrader.rb +33 -20
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +185 -172
- data/lib/alchemy_cms.rb +1 -7
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +0 -3
- data/lib/generators/alchemy/install/files/_article.html.erb +6 -4
- data/lib/generators/alchemy/install/files/alchemy.en.yml +22 -3
- data/lib/generators/alchemy/install/files/application.html.erb +5 -0
- data/lib/generators/alchemy/install/install_generator.rb +25 -23
- data/lib/generators/alchemy/install/templates/alchemy.rb.tt +200 -0
- data/lib/generators/alchemy/install/templates/dragonfly.rb.tt +0 -1
- data/lib/generators/alchemy/install/templates/elements.yml.tt +3 -1
- data/lib/generators/alchemy/install/templates/menus.yml.tt +1 -1
- data/lib/generators/alchemy/install/templates/page_layouts.yml.tt +2 -2
- data/lib/generators/alchemy/page_layouts/page_layouts_generator.rb +2 -2
- data/lib/tasks/alchemy/assets.rake +14 -0
- data/lib/tasks/alchemy/tidy.rake +6 -0
- data/lib/tasks/alchemy/upgrade.rake +12 -47
- data/vendor/assets/stylesheets/tinymce/skins/content/dark/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/content/default/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide/skin.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide-dark/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide-dark/skin.min.css +1 -0
- data/vendor/javascript/clipboard.min.js +1 -1
- data/vendor/javascript/cropperjs.min.js +1 -1
- data/vendor/javascript/handlebars.min.js +3 -3
- data/vendor/javascript/jquery.min.js +1 -1
- data/vendor/javascript/select2.min.js +3 -3
- data/vendor/javascript/shoelace.min.js +92 -76
- data/vendor/javascript/sortable.min.js +2 -2
- data/vendor/javascript/tinymce.min.js +1 -1
- data/vendor/javascript/ungap-custom-elements.min.js +2 -2
- metadata +223 -208
- data/CHANGELOG.md +0 -2041
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -73
- data/Gemfile +0 -71
- data/Rakefile +0 -102
- data/SECURITY.md +0 -13
- data/alchemy_cms.gemspec +0 -88
- data/app/assets/builds/alchemy/admin/page-select.css.map +0 -1
- data/app/assets/builds/alchemy/admin/print.css.map +0 -1
- data/app/assets/builds/alchemy/admin.css.map +0 -1
- data/app/assets/builds/alchemy/custom-properties.css +0 -1
- data/app/assets/builds/alchemy/custom-properties.css.map +0 -1
- data/app/assets/builds/alchemy/welcome.css.map +0 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +0 -1
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css.map +0 -1
- data/app/assets/javascripts/alchemy/admin.js +0 -10
- data/app/assets/stylesheets/alchemy/_defaults.scss +0 -3
- data/app/assets/stylesheets/alchemy/_deprecated_variables.scss +0 -45
- data/app/assets/stylesheets/alchemy/_deprecation.scss +0 -17
- data/app/assets/stylesheets/alchemy/_extends.scss +0 -62
- data/app/assets/stylesheets/alchemy/_variables.scss +0 -201
- data/app/assets/stylesheets/alchemy/admin/attachments.scss +0 -40
- data/app/assets/stylesheets/alchemy/admin/buttons.scss +0 -123
- data/app/assets/stylesheets/alchemy/admin/hints.scss +0 -5
- data/app/assets/stylesheets/alchemy/admin/labels.scss +0 -3
- data/app/assets/stylesheets/alchemy/admin/pagination.scss +0 -92
- data/app/assets/stylesheets/alchemy/admin/preview_window.scss +0 -33
- data/app/assets/stylesheets/alchemy/admin/resource_info.scss +0 -42
- data/app/assets/stylesheets/alchemy/admin/tags.scss +0 -158
- data/app/assets/stylesheets/alchemy/admin.scss +0 -42
- data/app/assets/stylesheets/alchemy/custom-properties.css +0 -98
- data/app/assets/stylesheets/alchemy/welcome.scss +0 -57
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.css +0 -711
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.css +0 -705
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.css +0 -29
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.css +0 -677
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.min.css +0 -7
- data/app/controllers/alchemy/elements_controller.rb +0 -32
- data/app/helpers/alchemy/admin/elements_helper.rb +0 -25
- data/app/models/alchemy/element/dom_id.rb +0 -31
- data/app/models/alchemy/picture/calculations.rb +0 -49
- data/app/models/alchemy/picture/transformations.rb +0 -115
- data/app/models/alchemy/picture/url.rb +0 -54
- data/app/views/alchemy/admin/attachments/destroy.js.erb +0 -1
- data/app/views/alchemy/admin/clipboard/clear.js.erb +0 -3
- data/app/views/alchemy/admin/clipboard/insert.js.erb +0 -29
- data/app/views/alchemy/admin/clipboard/remove.js.erb +0 -10
- data/app/views/alchemy/admin/resources/_filter.html.erb +0 -12
- data/app/views/alchemy/admin/resources/_resource.html.erb +0 -34
- data/app/views/alchemy/admin/resources/_table.html.erb +0 -29
- data/app/views/alchemy/elements/show.html.erb +0 -1
- data/app/views/alchemy/elements/show.js.erb +0 -1
- data/app/views/alchemy/ingredients/_audio_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_boolean_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_datetime_view.html.erb +0 -3
- data/app/views/alchemy/ingredients/_file_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_headline_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_html_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_link_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_node_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_page_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_picture_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_richtext_view.html.erb +0 -3
- data/app/views/alchemy/ingredients/_select_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_text_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_video_view.html.erb +0 -3
- data/babel.config.js +0 -12
- data/bin/importmap +0 -4
- data/bin/rails +0 -9
- data/bin/rspec +0 -3
- data/bin/setup +0 -30
- data/bin/start +0 -17
- data/bun.lockb +0 -0
- data/bundles/shoelace.js +0 -12
- data/bundles/tinymce.js +0 -22
- data/config/initializers/assets.rb +0 -4
- data/eslint.config.js +0 -17
- data/lib/alchemy/config.rb +0 -114
- data/lib/alchemy/element_definition.rb +0 -73
- data/lib/alchemy/page_layout.rb +0 -73
- data/lib/alchemy/resource_filter.rb +0 -40
- data/lib/alchemy/upgrader/seven_point_four.rb +0 -26
- data/lib/alchemy/upgrader/seven_point_three.rb +0 -52
- data/lib/alchemy/upgrader/tasks/.keep +0 -0
- data/lib/generators/alchemy/ingredient/templates/view.html.erb +0 -1
- data/lib/generators/alchemy/install/files/alchemy_admin.js +0 -1
- data/lib/generators/alchemy/install/files/all.js +0 -11
- data/lib/generators/alchemy/install/files/article.css +0 -25
- data/rollup.config.mjs +0 -108
- data/vendor/assets/images/remixicon.symbol.svg +0 -11
- /data/app/{assets/stylesheets → stylesheets}/alchemy/_fonts.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/attachment-select.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/flash.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/list_filter.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/spinner.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/tinymce/skins/skintool.json +0 -0
- /data/app/{assets/stylesheets → stylesheets}/tinymce/skins/ui/alchemy/fonts/tinymce-mobile.woff +0 -0
@@ -1,21 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "csv"
|
4
|
-
require "alchemy/resource"
|
5
|
-
require "alchemy/resources_helper"
|
6
|
-
require "alchemy/resource_filter"
|
7
4
|
|
8
5
|
module Alchemy
|
9
6
|
module Admin
|
10
7
|
class ResourcesController < Alchemy::Admin::BaseController
|
11
|
-
COMMON_SEARCH_FILTER_EXCLUDES = %i[id utf8 _method _ format].freeze
|
12
|
-
|
13
8
|
include Alchemy::ResourcesHelper
|
9
|
+
extend Alchemy::Admin::ResourceName
|
10
|
+
include Alchemy::Admin::ResourceFilter
|
14
11
|
|
15
12
|
helper Alchemy::ResourcesHelper, TagsHelper
|
16
|
-
helper_method :resource_handler, :
|
17
|
-
:items_per_page, :items_per_page_options, :resource_has_filters,
|
18
|
-
:resource_filters_for_select
|
13
|
+
helper_method :resource_handler, :items_per_page, :items_per_page_options
|
19
14
|
|
20
15
|
before_action :load_resource,
|
21
16
|
only: %i[show edit update destroy]
|
@@ -29,21 +24,20 @@ module Alchemy
|
|
29
24
|
|
30
25
|
items = items.includes(*resource_relations_names) if contains_relations?
|
31
26
|
items = items.tagged_with(search_filter_params[:tagged_with]) if search_filter_params[:tagged_with].present?
|
32
|
-
items = apply_filters(items) if search_filter_params[:filter].present?
|
33
27
|
|
34
28
|
respond_to do |format|
|
35
29
|
format.html do
|
36
30
|
items = items.page(params[:page] || 1).per(items_per_page)
|
37
|
-
instance_variable_set(:"@#{
|
31
|
+
instance_variable_set(:"@#{resources_name}", items)
|
38
32
|
end
|
39
33
|
format.csv do
|
40
|
-
instance_variable_set(:"@#{
|
34
|
+
instance_variable_set(:"@#{resources_name}", items)
|
41
35
|
end
|
42
36
|
end
|
43
37
|
end
|
44
38
|
|
45
39
|
def new
|
46
|
-
instance_variable_set(:"@#{
|
40
|
+
instance_variable_set(:"@#{resource_name}", resource_handler.model.new)
|
47
41
|
end
|
48
42
|
|
49
43
|
def show
|
@@ -54,7 +48,7 @@ module Alchemy
|
|
54
48
|
end
|
55
49
|
|
56
50
|
def create
|
57
|
-
instance_variable_set(:"@#{
|
51
|
+
instance_variable_set(:"@#{resource_name}", resource_handler.model.new(resource_params))
|
58
52
|
resource_instance_variable.save
|
59
53
|
render_errors_or_redirect(
|
60
54
|
resource_instance_variable,
|
@@ -85,62 +79,8 @@ module Alchemy
|
|
85
79
|
@_resource_handler ||= Alchemy::Resource.new(controller_path, alchemy_module)
|
86
80
|
end
|
87
81
|
|
88
|
-
def resource_has_filters
|
89
|
-
resource_model.respond_to?(:alchemy_resource_filters)
|
90
|
-
end
|
91
|
-
|
92
|
-
def resource_has_deprecated_filters
|
93
|
-
resource_model.alchemy_resource_filters.any? { |f| !f.is_a?(Hash) }
|
94
|
-
end
|
95
|
-
|
96
|
-
def resource_filters
|
97
|
-
return unless resource_has_filters
|
98
|
-
|
99
|
-
@_resource_filters ||= resource_model.alchemy_resource_filters
|
100
|
-
end
|
101
|
-
|
102
|
-
def resource_filters_for_select
|
103
|
-
resource_filters.map do |filter|
|
104
|
-
ResourceFilter.new(filter, resource_handler.resource_name)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
82
|
protected
|
109
83
|
|
110
|
-
def apply_filters(items)
|
111
|
-
sanitize_filter_params!
|
112
|
-
|
113
|
-
search_filter_params[:filter].each do |filter|
|
114
|
-
if argument_scope_filter?(filter)
|
115
|
-
items = items.public_send(filter[0], filter[1])
|
116
|
-
elsif simple_scope_filter?(filter)
|
117
|
-
items = items.public_send(filter[1])
|
118
|
-
else
|
119
|
-
raise "Can't apply filter #{filter[0]}. Either the name or the values must be defined as class methods / scopes on the model."
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
items
|
124
|
-
end
|
125
|
-
|
126
|
-
def simple_scope_filter?(filter)
|
127
|
-
resource_model.respond_to?(filter[1])
|
128
|
-
end
|
129
|
-
|
130
|
-
def argument_scope_filter?(filter)
|
131
|
-
resource_model.respond_to?(filter[0])
|
132
|
-
end
|
133
|
-
|
134
|
-
def sanitize_filter_params!
|
135
|
-
search_filter_params[:filter].reject! do |_, v|
|
136
|
-
eligible_resource_filter_values.exclude?(v)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def eligible_resource_filter_values
|
141
|
-
resource_filters.map(&:values).flatten!.map!(&:to_s)
|
142
|
-
end
|
143
|
-
|
144
84
|
# Returns a translated +flash[:notice]+ for current controller action.
|
145
85
|
def flash_notice_for_resource_action(action = action_name)
|
146
86
|
return if resource_instance_variable.errors.any?
|
@@ -174,61 +114,31 @@ module Alchemy
|
|
174
114
|
end
|
175
115
|
|
176
116
|
def load_resource
|
177
|
-
instance_variable_set(:"@#{
|
117
|
+
instance_variable_set(:"@#{resource_name}", resource_handler.model.find(params[:id]))
|
178
118
|
end
|
179
119
|
|
180
120
|
def authorize_resource
|
181
121
|
authorize!(action_name.to_sym, resource_instance_variable || resource_handler.model)
|
182
122
|
end
|
183
123
|
|
184
|
-
# Permits all
|
185
|
-
#
|
186
|
-
# THIS IS INSECURE! Although only signed in admin users can send requests anyway, but we should change this.
|
124
|
+
# Permits all editable resource attributes as default.
|
187
125
|
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
# TODO: Hook this into authorization provider.
|
126
|
+
# Define this method in your inheriting controller if you want to permit additional attributes.
|
191
127
|
#
|
128
|
+
# @see Alchemy::Resource#editable_attributes
|
192
129
|
def resource_params
|
193
|
-
params.require(resource_handler.namespaced_resource_name).permit
|
194
|
-
|
195
|
-
|
196
|
-
def search_filter_params
|
197
|
-
@_search_filter_params ||= params.except(*COMMON_SEARCH_FILTER_EXCLUDES).permit(*common_search_filter_includes).to_h
|
198
|
-
end
|
199
|
-
|
200
|
-
def common_search_filter_includes
|
201
|
-
search_filters = [
|
202
|
-
{
|
203
|
-
q: [:s] + permitted_ransack_search_fields
|
204
|
-
},
|
205
|
-
:tagged_with,
|
206
|
-
:page,
|
207
|
-
:per_page
|
208
|
-
]
|
209
|
-
|
210
|
-
if resource_has_filters
|
211
|
-
search_filters << {
|
212
|
-
filter: resource_filters.map { |f| f[:name] }
|
213
|
-
}
|
214
|
-
end
|
215
|
-
|
216
|
-
search_filters
|
217
|
-
end
|
218
|
-
|
219
|
-
def permitted_ransack_search_fields
|
220
|
-
[
|
221
|
-
resource_handler.search_field_name
|
222
|
-
]
|
130
|
+
params.require(resource_handler.namespaced_resource_name).permit(
|
131
|
+
resource_handler.editable_attributes.map { _1[:name] }
|
132
|
+
)
|
223
133
|
end
|
224
134
|
|
225
135
|
def items_per_page
|
226
136
|
cookies[:alchemy_items_per_page] =
|
227
|
-
params[:per_page] || cookies[:alchemy_items_per_page] || Alchemy
|
137
|
+
params[:per_page] || cookies[:alchemy_items_per_page] || Alchemy.config.items_per_page
|
228
138
|
end
|
229
139
|
|
230
140
|
def items_per_page_options
|
231
|
-
per_page = Alchemy
|
141
|
+
per_page = Alchemy.config.items_per_page
|
232
142
|
[per_page, per_page * 2, per_page * 4]
|
233
143
|
end
|
234
144
|
|
@@ -2,37 +2,66 @@
|
|
2
2
|
|
3
3
|
module Alchemy
|
4
4
|
class AttachmentsController < BaseController
|
5
|
+
if Alchemy.storage_adapter.active_storage?
|
6
|
+
include ActiveStorage::Streaming
|
7
|
+
end
|
8
|
+
|
5
9
|
before_action :load_attachment
|
6
10
|
authorize_resource class: Alchemy::Attachment
|
7
11
|
|
12
|
+
self.etag_with_template_digest = false
|
13
|
+
|
8
14
|
# sends file inline. i.e. for viewing pdfs/movies in browser
|
9
15
|
def show
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
type: @attachment.file_mime_type,
|
16
|
-
disposition: "inline"
|
17
|
-
}
|
18
|
-
)
|
16
|
+
if Alchemy.storage_adapter.dragonfly?
|
17
|
+
send_attachment_file(disposition: :inline)
|
18
|
+
else
|
19
|
+
send_attachment_blob(disposition: :inline)
|
20
|
+
end
|
19
21
|
end
|
20
22
|
|
21
23
|
# sends file as attachment. aka download
|
22
24
|
def download
|
25
|
+
if Alchemy.storage_adapter.dragonfly?
|
26
|
+
send_attachment_file(disposition: :attachment)
|
27
|
+
else
|
28
|
+
send_attachment_blob(disposition: :attachment)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def load_attachment
|
35
|
+
@attachment = Attachment.find(params[:id])
|
36
|
+
end
|
37
|
+
|
38
|
+
def send_attachment_file(disposition: :inline)
|
23
39
|
response.headers["Content-Length"] = @attachment.file.size.to_s
|
40
|
+
|
24
41
|
send_file(
|
25
|
-
@attachment.file.path,
|
42
|
+
@attachment.file.path,
|
43
|
+
{
|
26
44
|
filename: @attachment.file_name,
|
27
|
-
type: @attachment.file_mime_type
|
45
|
+
type: @attachment.file_mime_type,
|
46
|
+
disposition: disposition
|
28
47
|
}
|
29
48
|
)
|
30
49
|
end
|
31
50
|
|
32
|
-
|
51
|
+
def send_attachment_blob(disposition: :inline)
|
52
|
+
@blob = @attachment.file.blob
|
33
53
|
|
34
|
-
|
35
|
-
|
54
|
+
if request.headers["Range"].present?
|
55
|
+
send_blob_byte_range_data @blob, request.headers["Range"], disposition: disposition
|
56
|
+
else
|
57
|
+
http_cache_forever public: true do
|
58
|
+
response.headers["Accept-Ranges"] = "bytes"
|
59
|
+
send_blob_stream @blob, disposition: disposition
|
60
|
+
# Rails ActionController::Live removes the Content-Length header,
|
61
|
+
# but browsers need that to be able to show a progress bar during download.
|
62
|
+
response.headers["Content-Length"] = @blob.byte_size.to_s
|
63
|
+
end
|
64
|
+
end
|
36
65
|
end
|
37
66
|
end
|
38
67
|
end
|
@@ -106,7 +106,12 @@ module Alchemy
|
|
106
106
|
def load_index_page
|
107
107
|
@page ||= Language.current_root_page
|
108
108
|
Current.page = @page
|
109
|
-
|
109
|
+
|
110
|
+
if signup_required? && @page.nil?
|
111
|
+
render template: "alchemy/welcome", layout: false
|
112
|
+
elsif !@page&.public?
|
113
|
+
render template: "alchemy/no_index", layout: false
|
114
|
+
end
|
110
115
|
end
|
111
116
|
|
112
117
|
# == Loads page by urlname
|
@@ -186,13 +191,25 @@ module Alchemy
|
|
186
191
|
if must_not_cache?
|
187
192
|
expires_now
|
188
193
|
else
|
189
|
-
expires_in @page.expiration_time, public: !@page.restricted
|
194
|
+
expires_in @page.expiration_time, {public: !@page.restricted}.merge(caching_options)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def caching_options
|
199
|
+
if Alchemy.config.page_cache.stale_while_revalidate
|
200
|
+
{
|
201
|
+
stale_while_revalidate: Alchemy.config.page_cache.stale_while_revalidate
|
202
|
+
}
|
203
|
+
else
|
204
|
+
{
|
205
|
+
must_revalidate: true
|
206
|
+
}
|
190
207
|
end
|
191
208
|
end
|
192
209
|
|
193
210
|
def signup_required?
|
194
211
|
if Alchemy.user_class.respond_to?(:admins)
|
195
|
-
Alchemy.user_class.admins.empty?
|
212
|
+
Alchemy.user_class.admins.empty?
|
196
213
|
end
|
197
214
|
end
|
198
215
|
|
@@ -224,7 +241,12 @@ module Alchemy
|
|
224
241
|
|
225
242
|
# don't cache pages if we have flash message to display or the page has caching disabled
|
226
243
|
def must_not_cache?
|
227
|
-
|
244
|
+
!caching_enabled? || !@page.cache_page? || flash.present?
|
245
|
+
end
|
246
|
+
|
247
|
+
def caching_enabled?
|
248
|
+
Rails.application.config.action_controller.perform_caching &&
|
249
|
+
Alchemy.config.cache_pages
|
228
250
|
end
|
229
251
|
|
230
252
|
def page_not_found!
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Admin
|
5
|
+
module ResourceFilter
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
COMMON_SEARCH_FILTER_EXCLUDES = %i[id utf8 _method _ format].freeze
|
9
|
+
|
10
|
+
included do
|
11
|
+
prepend_before_action :initialize_alchemy_filters
|
12
|
+
helper_method :alchemy_filters, :search_form_name, :applied_filters, :search_filter_params, :resource_has_filters
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
# Adds a filter to the resource.
|
17
|
+
# @param name [String, Symbol] The name of the filter.
|
18
|
+
# @param type [Symbol] The type of the filter. Can currently be `:select` or `:checkbox`.
|
19
|
+
# @param args [Hash] Additional arguments for the filter.
|
20
|
+
# @example
|
21
|
+
# add_alchemy_filter :by_location, type: :select, options: ->(query) { Location.pluck(:name, :id) }
|
22
|
+
# add_alchemy_filter :future, type: :checkbox
|
23
|
+
# add_alchemy_filter :by_timeframe, type: :select, options: ["today", "tomorrow"]
|
24
|
+
def add_alchemy_filter(name, type:, **args)
|
25
|
+
alchemy_filters << "Alchemy::Admin::Filters::#{type.to_s.camelize}".constantize.new(
|
26
|
+
name:,
|
27
|
+
resource_name:,
|
28
|
+
**args
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def alchemy_filters
|
33
|
+
@alchemy_filters ||= []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
delegate :alchemy_filters, to: :class
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def initialize_alchemy_filters
|
41
|
+
return if alchemy_filters.any?
|
42
|
+
return unless resource_model.respond_to?(:alchemy_resource_filters)
|
43
|
+
Alchemy::Deprecation.warn(
|
44
|
+
"The `alchemy_resource_filters` method is deprecated and will be removed in Alchemy 8.1. " \
|
45
|
+
"Please use `add_alchemy_filter` in your controller instead. Make sure to safelist the scopes " \
|
46
|
+
"you want to use in the `ransackable_scopes` method of your model."
|
47
|
+
)
|
48
|
+
resource_model.alchemy_resource_filters.each do |filter_config|
|
49
|
+
if resource_model.respond_to?(filter_config[:name])
|
50
|
+
self.class.add_alchemy_filter filter_config[:name], type: :select, options: filter_config[:values]
|
51
|
+
else
|
52
|
+
filter_config[:values].each do |scope|
|
53
|
+
self.class.add_alchemy_filter scope, type: :checkbox
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def search_filter_params
|
60
|
+
@_search_filter_params ||= params.except(*COMMON_SEARCH_FILTER_EXCLUDES).permit(*common_search_filter_includes).to_h
|
61
|
+
end
|
62
|
+
|
63
|
+
def common_search_filter_includes
|
64
|
+
[
|
65
|
+
{
|
66
|
+
q: [:s] + permitted_ransack_search_fields
|
67
|
+
},
|
68
|
+
:tagged_with,
|
69
|
+
:page,
|
70
|
+
:per_page
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def permitted_ransack_search_fields
|
75
|
+
[
|
76
|
+
resource_handler.search_field_name
|
77
|
+
] + alchemy_filters.map(&:name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def resource_has_filters
|
81
|
+
alchemy_filters.any?
|
82
|
+
end
|
83
|
+
|
84
|
+
def applied_filters
|
85
|
+
return [] unless search_filter_params[:q]
|
86
|
+
|
87
|
+
alchemy_filters.select do |alchemy_filter|
|
88
|
+
search_filter_params[:q][alchemy_filter.name].present?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -14,7 +14,7 @@ module Alchemy
|
|
14
14
|
#
|
15
15
|
# @return Array<Alchemy::IngredientEditor>
|
16
16
|
def ingredients
|
17
|
-
|
17
|
+
ingredient_definitions.map do |ingredient|
|
18
18
|
Alchemy::IngredientEditor.new(find_or_create_ingredient(ingredient))
|
19
19
|
end
|
20
20
|
end
|
@@ -22,7 +22,7 @@ module Alchemy
|
|
22
22
|
# Are any ingredients defined?
|
23
23
|
# @return [Boolean]
|
24
24
|
def has_ingredients_defined?
|
25
|
-
|
25
|
+
ingredient_definitions.any?
|
26
26
|
end
|
27
27
|
|
28
28
|
# Returns the translated ingredient group for displaying in admin editor group headings
|
@@ -77,56 +77,13 @@ module Alchemy
|
|
77
77
|
super
|
78
78
|
end
|
79
79
|
|
80
|
-
# Returns a deprecation notice for elements marked deprecated
|
81
|
-
#
|
82
|
-
# You can either use localizations or pass a String as notice
|
83
|
-
# in the element definition.
|
84
|
-
#
|
85
|
-
# == Custom deprecation notices
|
86
|
-
#
|
87
|
-
# Use general element deprecation notice
|
88
|
-
#
|
89
|
-
# - name: old_element
|
90
|
-
# deprecated: true
|
91
|
-
#
|
92
|
-
# Add a translation to your locale file for a per element notice.
|
93
|
-
#
|
94
|
-
# en:
|
95
|
-
# alchemy:
|
96
|
-
# element_deprecation_notices:
|
97
|
-
# old_element: Foo baz widget is deprecated
|
98
|
-
#
|
99
|
-
# or use the global translation that apply to all deprecated elements.
|
100
|
-
#
|
101
|
-
# en:
|
102
|
-
# alchemy:
|
103
|
-
# element_deprecation_notice: Foo baz widget is deprecated
|
104
|
-
#
|
105
|
-
# or pass string as deprecation notice.
|
106
|
-
#
|
107
|
-
# - name: old_element
|
108
|
-
# deprecated: This element will be removed soon.
|
109
|
-
#
|
110
|
-
def deprecation_notice
|
111
|
-
case definition["deprecated"]
|
112
|
-
when String
|
113
|
-
definition["deprecated"]
|
114
|
-
when TrueClass
|
115
|
-
Alchemy.t(
|
116
|
-
name,
|
117
|
-
scope: :element_deprecation_notices,
|
118
|
-
default: Alchemy.t(:element_deprecated)
|
119
|
-
)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
80
|
private
|
124
81
|
|
125
82
|
def find_or_create_ingredient(definition)
|
126
|
-
element.ingredients.detect {
|
83
|
+
element.ingredients.detect { _1.role == definition.role } ||
|
127
84
|
element.ingredients.create!(
|
128
|
-
role: definition
|
129
|
-
type: Alchemy::Ingredient.normalize_type(definition
|
85
|
+
role: definition.role,
|
86
|
+
type: Alchemy::Ingredient.normalize_type(definition.type)
|
130
87
|
)
|
131
88
|
end
|
132
89
|
end
|
@@ -99,62 +99,12 @@ module Alchemy
|
|
99
99
|
Logger.warn("ingredient #{role} is missing its definition", caller(1..1))
|
100
100
|
Alchemy.t(:ingredient_definition_missing)
|
101
101
|
else
|
102
|
-
deprecation_notice
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Returns a deprecation notice for ingredients marked deprecated
|
107
|
-
#
|
108
|
-
# You can either use localizations or pass a String as notice
|
109
|
-
# in the ingredient definition.
|
110
|
-
#
|
111
|
-
# == Custom deprecation notices
|
112
|
-
#
|
113
|
-
# Use general ingredient deprecation notice
|
114
|
-
#
|
115
|
-
# - name: element_name
|
116
|
-
# ingredients:
|
117
|
-
# - role: old_ingredient
|
118
|
-
# type: Text
|
119
|
-
# deprecated: true
|
120
|
-
#
|
121
|
-
# Add a translation to your locale file for a per ingredient notice.
|
122
|
-
#
|
123
|
-
# en:
|
124
|
-
# alchemy:
|
125
|
-
# ingredient_deprecation_notices:
|
126
|
-
# element_name:
|
127
|
-
# old_ingredient: Foo baz widget is deprecated
|
128
|
-
#
|
129
|
-
# or use the global translation that apply to all deprecated ingredients.
|
130
|
-
#
|
131
|
-
# en:
|
132
|
-
# alchemy:
|
133
|
-
# ingredient_deprecation_notice: Foo baz widget is deprecated
|
134
|
-
#
|
135
|
-
# or pass string as deprecation notice.
|
136
|
-
#
|
137
|
-
# - name: element_name
|
138
|
-
# ingredients:
|
139
|
-
# - role: old_ingredient
|
140
|
-
# type: Text
|
141
|
-
# deprecated: This ingredient will be removed soon.
|
142
|
-
#
|
143
|
-
def deprecation_notice
|
144
|
-
case definition[:deprecated]
|
145
|
-
when String
|
146
|
-
definition[:deprecated]
|
147
|
-
when TrueClass
|
148
|
-
Alchemy.t(
|
149
|
-
role,
|
150
|
-
scope: [:ingredient_deprecation_notices, element.name],
|
151
|
-
default: Alchemy.t(:ingredient_deprecated)
|
152
|
-
)
|
102
|
+
definition.deprecation_notice(element_name: element&.name)
|
153
103
|
end
|
154
104
|
end
|
155
105
|
|
156
106
|
def validations
|
157
|
-
definition.
|
107
|
+
definition.validate
|
158
108
|
end
|
159
109
|
|
160
110
|
def format_validation
|
@@ -173,7 +123,7 @@ module Alchemy
|
|
173
123
|
private
|
174
124
|
|
175
125
|
def form_field_counter
|
176
|
-
element.
|
126
|
+
element.ingredient_definitions.index { _1.role == role }
|
177
127
|
end
|
178
128
|
end
|
179
129
|
end
|
@@ -12,12 +12,12 @@ module Alchemy
|
|
12
12
|
|
13
13
|
def attachment_preview_size(attachment)
|
14
14
|
case attachment.file_mime_type
|
15
|
-
when
|
16
|
-
when *
|
17
|
-
when *
|
18
|
-
when
|
15
|
+
when "application/pdf" then "850x600"
|
16
|
+
when *IMAGE_FILE_TYPES then "850x280"
|
17
|
+
when *AUDIO_FILE_TYPES then "850x190"
|
18
|
+
when *VIDEO_FILE_TYPES then "900x280"
|
19
19
|
else
|
20
|
-
"
|
20
|
+
"500x165"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|