lc_alchemy_cms 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +23 -0
- data/.gitignore +21 -0
- data/.hound.yml +2 -0
- data/.rspec +1 -0
- data/.rubocop.yml +861 -0
- data/.teatro.yml +7 -0
- data/.travis.yml +27 -0
- data/.yardopts +5 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +73 -0
- data/Gemfile +34 -0
- data/LICENSE +27 -0
- data/README.md +297 -0
- data/Rakefile +48 -0
- data/alchemy_cms.gemspec +81 -0
- data/app/assets/fonts/alchemy/icons.eot +0 -0
- data/app/assets/fonts/alchemy/icons.svg +71 -0
- data/app/assets/fonts/alchemy/icons.ttf +0 -0
- data/app/assets/fonts/alchemy/icons.woff +0 -0
- data/app/assets/images/alchemy/alchemy-logo.svg +70 -0
- data/app/assets/images/alchemy/favicon.ico +0 -0
- data/app/assets/images/alchemy/icon.svg +14 -0
- data/app/assets/images/alchemy/icons.png +0 -0
- data/app/assets/images/alchemy/lupe.cur +0 -0
- data/app/assets/images/alchemy/ui-icons_666666_256x240.png +0 -0
- data/app/assets/images/sassy-ie-overlay.png +0 -0
- data/app/assets/javascripts/alchemy/alchemy.autocomplete.js.coffee +30 -0
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +142 -0
- data/app/assets/javascripts/alchemy/alchemy.browser.js.coffee +22 -0
- data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +32 -0
- data/app/assets/javascripts/alchemy/alchemy.char_counter.js.coffee +19 -0
- data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +85 -0
- data/app/assets/javascripts/alchemy/alchemy.custom.js +1 -0
- data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +31 -0
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +266 -0
- data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +84 -0
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +138 -0
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +89 -0
- data/app/assets/javascripts/alchemy/alchemy.file_progress.js.coffee +63 -0
- data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +27 -0
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +22 -0
- data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +49 -0
- data/app/assets/javascripts/alchemy/alchemy.html5.js +22 -0
- data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +26 -0
- data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +44 -0
- data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +63 -0
- data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +42 -0
- data/app/assets/javascripts/alchemy/alchemy.js +52 -0
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +250 -0
- data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +49 -0
- data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +48 -0
- data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +106 -0
- data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +58 -0
- data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +50 -0
- data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +49 -0
- data/app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee +11 -0
- data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +66 -0
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +132 -0
- data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +102 -0
- data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +42 -0
- data/app/assets/javascripts/alchemy/menubar.js.coffee +8 -0
- data/app/assets/javascripts/alchemy/preview.js +1 -0
- data/app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js +19 -0
- data/app/assets/stylesheets/alchemy/_defaults.scss +8 -0
- data/app/assets/stylesheets/alchemy/_extends.scss +93 -0
- data/app/assets/stylesheets/alchemy/_mixins.scss +112 -0
- data/app/assets/stylesheets/alchemy/_variables.scss +61 -0
- data/app/assets/stylesheets/alchemy/admin.scss +31 -0
- data/app/assets/stylesheets/alchemy/archive.scss +436 -0
- data/app/assets/stylesheets/alchemy/base.scss +609 -0
- data/app/assets/stylesheets/alchemy/buttons.scss +259 -0
- data/app/assets/stylesheets/alchemy/custom.scss +1 -0
- data/app/assets/stylesheets/alchemy/dashboard.scss +104 -0
- data/app/assets/stylesheets/alchemy/dialogs.scss +214 -0
- data/app/assets/stylesheets/alchemy/elements.scss +772 -0
- data/app/assets/stylesheets/alchemy/errors.scss +39 -0
- data/app/assets/stylesheets/alchemy/flash.scss +65 -0
- data/app/assets/stylesheets/alchemy/form_fields.scss +89 -0
- data/app/assets/stylesheets/alchemy/forms.scss +193 -0
- data/app/assets/stylesheets/alchemy/frame.scss +301 -0
- data/app/assets/stylesheets/alchemy/icon-font.scss +67 -0
- data/app/assets/stylesheets/alchemy/icons.scss +324 -0
- data/app/assets/stylesheets/alchemy/jquery-ui.scss +1511 -0
- data/app/assets/stylesheets/alchemy/menubar.scss +81 -0
- data/app/assets/stylesheets/alchemy/modules.scss +33 -0
- data/app/assets/stylesheets/alchemy/notices.scss +64 -0
- data/app/assets/stylesheets/alchemy/pagination.scss +65 -0
- data/app/assets/stylesheets/alchemy/print.scss +34 -0
- data/app/assets/stylesheets/alchemy/search.scss +73 -0
- data/app/assets/stylesheets/alchemy/selects.scss +235 -0
- data/app/assets/stylesheets/alchemy/sitemap.scss +385 -0
- data/app/assets/stylesheets/alchemy/tables.scss +218 -0
- data/app/assets/stylesheets/alchemy/toolbar.scss +146 -0
- data/app/assets/stylesheets/alchemy/upload.scss +121 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +90 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/readme.md +1 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.eot +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +175 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.eot +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +153 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/anchor.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/loader.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/object.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/trans.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/wline.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.ie7.min.css +1 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +1810 -0
- data/app/controllers/alchemy/admin/attachments_controller.rb +106 -0
- data/app/controllers/alchemy/admin/base_controller.rb +168 -0
- data/app/controllers/alchemy/admin/clipboard_controller.rb +51 -0
- data/app/controllers/alchemy/admin/contents_controller.rb +76 -0
- data/app/controllers/alchemy/admin/dashboard_controller.rb +89 -0
- data/app/controllers/alchemy/admin/elements_controller.rb +190 -0
- data/app/controllers/alchemy/admin/essence_files_controller.rb +47 -0
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +120 -0
- data/app/controllers/alchemy/admin/languages_controller.rb +17 -0
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +19 -0
- data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +39 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +359 -0
- data/app/controllers/alchemy/admin/pictures_controller.rb +168 -0
- data/app/controllers/alchemy/admin/resources_controller.rb +185 -0
- data/app/controllers/alchemy/admin/sites_controller.rb +6 -0
- data/app/controllers/alchemy/admin/tags_controller.rb +76 -0
- data/app/controllers/alchemy/admin/trash_controller.rb +27 -0
- data/app/controllers/alchemy/api/base_controller.rb +19 -0
- data/app/controllers/alchemy/api/contents_controller.rb +35 -0
- data/app/controllers/alchemy/api/elements_controller.rb +29 -0
- data/app/controllers/alchemy/api/pages_controller.rb +32 -0
- data/app/controllers/alchemy/attachments_controller.rb +35 -0
- data/app/controllers/alchemy/base_controller.rb +106 -0
- data/app/controllers/alchemy/elements_controller.rb +27 -0
- data/app/controllers/alchemy/messages_controller.rb +114 -0
- data/app/controllers/alchemy/pages_controller.rb +211 -0
- data/app/controllers/alchemy/pictures_controller.rb +82 -0
- data/app/helpers/alchemy/admin/attachments_helper.rb +12 -0
- data/app/helpers/alchemy/admin/base_helper.rb +471 -0
- data/app/helpers/alchemy/admin/contents_helper.rb +113 -0
- data/app/helpers/alchemy/admin/elements_helper.rb +134 -0
- data/app/helpers/alchemy/admin/essences_helper.rb +120 -0
- data/app/helpers/alchemy/admin/form_helper.rb +30 -0
- data/app/helpers/alchemy/admin/navigation_helper.rb +238 -0
- data/app/helpers/alchemy/admin/pages_helper.rb +70 -0
- data/app/helpers/alchemy/admin/pictures_helper.rb +30 -0
- data/app/helpers/alchemy/admin/tags_helper.rb +102 -0
- data/app/helpers/alchemy/base_helper.rb +81 -0
- data/app/helpers/alchemy/elements_block_helper.rb +162 -0
- data/app/helpers/alchemy/elements_helper.rb +291 -0
- data/app/helpers/alchemy/essences_helper.rb +138 -0
- data/app/helpers/alchemy/pages_helper.rb +417 -0
- data/app/helpers/alchemy/url_helper.rb +76 -0
- data/app/mailers/alchemy/messages.rb +15 -0
- data/app/models/alchemy.rb +7 -0
- data/app/models/alchemy/attachment.rb +129 -0
- data/app/models/alchemy/cell.rb +94 -0
- data/app/models/alchemy/content.rb +255 -0
- data/app/models/alchemy/content/factory.rb +190 -0
- data/app/models/alchemy/element.rb +513 -0
- data/app/models/alchemy/element/definitions.rb +52 -0
- data/app/models/alchemy/element/presenters.rb +87 -0
- data/app/models/alchemy/element_to_page.rb +7 -0
- data/app/models/alchemy/essence_boolean.rb +19 -0
- data/app/models/alchemy/essence_date.rb +24 -0
- data/app/models/alchemy/essence_file.rb +42 -0
- data/app/models/alchemy/essence_html.rb +23 -0
- data/app/models/alchemy/essence_link.rb +20 -0
- data/app/models/alchemy/essence_picture.rb +152 -0
- data/app/models/alchemy/essence_richtext.rb +47 -0
- data/app/models/alchemy/essence_select.rb +18 -0
- data/app/models/alchemy/essence_text.rb +22 -0
- data/app/models/alchemy/folded_page.rb +16 -0
- data/app/models/alchemy/language.rb +144 -0
- data/app/models/alchemy/language/code.rb +22 -0
- data/app/models/alchemy/legacy_page_url.rb +20 -0
- data/app/models/alchemy/message.rb +40 -0
- data/app/models/alchemy/page.rb +409 -0
- data/app/models/alchemy/page/page_cells.rb +71 -0
- data/app/models/alchemy/page/page_elements.rb +272 -0
- data/app/models/alchemy/page/page_naming.rb +122 -0
- data/app/models/alchemy/page/page_natures.rb +114 -0
- data/app/models/alchemy/page/page_scopes.rb +95 -0
- data/app/models/alchemy/page/page_users.rb +58 -0
- data/app/models/alchemy/picture.rb +220 -0
- data/app/models/alchemy/picture/sweeping.rb +17 -0
- data/app/models/alchemy/picture/transformations.rb +256 -0
- data/app/models/alchemy/site.rb +91 -0
- data/app/models/alchemy/site/layout.rb +38 -0
- data/app/models/alchemy/tag.rb +24 -0
- data/app/models/alchemy/translations.rb +7 -0
- data/app/models/alchemy/translations/essence_body_updater.rb +64 -0
- data/app/models/alchemy/translations/translation_pusher.rb +18 -0
- data/app/models/alchemy/tree_node.rb +4 -0
- data/app/serializers/alchemy/attachment_serializer.rb +15 -0
- data/app/serializers/alchemy/cell_serializer.rb +18 -0
- data/app/serializers/alchemy/content_serializer.rb +20 -0
- data/app/serializers/alchemy/element_serializer.rb +20 -0
- data/app/serializers/alchemy/essence_boolean_serializer.rb +11 -0
- data/app/serializers/alchemy/essence_date_serializer.rb +11 -0
- data/app/serializers/alchemy/essence_file_serializer.rb +12 -0
- data/app/serializers/alchemy/essence_html_serializer.rb +11 -0
- data/app/serializers/alchemy/essence_link_serializer.rb +14 -0
- data/app/serializers/alchemy/essence_picture_serializer.rb +28 -0
- data/app/serializers/alchemy/essence_richtext_serializer.rb +12 -0
- data/app/serializers/alchemy/essence_select_serializer.rb +11 -0
- data/app/serializers/alchemy/essence_text_serializer.rb +22 -0
- data/app/serializers/alchemy/legacy_element_serializer.rb +17 -0
- data/app/serializers/alchemy/page_serializer.rb +29 -0
- data/app/serializers/alchemy/picture_serializer.rb +16 -0
- data/app/views/alchemy/_menubar.html.erb +16 -0
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +32 -0
- data/app/views/alchemy/admin/attachments/_attachment.html.erb +63 -0
- data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +15 -0
- data/app/views/alchemy/admin/attachments/_files_list.html.erb +39 -0
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +11 -0
- data/app/views/alchemy/admin/attachments/_tag_list.html.erb +14 -0
- data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +7 -0
- data/app/views/alchemy/admin/attachments/create.js.erb +11 -0
- data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -0
- data/app/views/alchemy/admin/attachments/edit.html.erb +10 -0
- data/app/views/alchemy/admin/attachments/index.html.erb +29 -0
- data/app/views/alchemy/admin/attachments/new.html.erb +14 -0
- data/app/views/alchemy/admin/attachments/show.html.erb +3 -0
- data/app/views/alchemy/admin/clipboard/clear.js.erb +3 -0
- data/app/views/alchemy/admin/clipboard/index.html.erb +22 -0
- data/app/views/alchemy/admin/clipboard/insert.js.erb +19 -0
- data/app/views/alchemy/admin/clipboard/remove.js.erb +10 -0
- data/app/views/alchemy/admin/contents/_missing.html.erb +19 -0
- data/app/views/alchemy/admin/contents/create.js.erb +56 -0
- data/app/views/alchemy/admin/contents/destroy.js.erb +4 -0
- data/app/views/alchemy/admin/contents/new.html.erb +11 -0
- data/app/views/alchemy/admin/contents/order.js.erb +3 -0
- data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +38 -0
- data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +22 -0
- data/app/views/alchemy/admin/dashboard/_sites.html.erb +23 -0
- data/app/views/alchemy/admin/dashboard/_users.html.erb +19 -0
- data/app/views/alchemy/admin/dashboard/help.html.erb +21 -0
- data/app/views/alchemy/admin/dashboard/index.html.erb +44 -0
- data/app/views/alchemy/admin/dashboard/info.html.erb +64 -0
- data/app/views/alchemy/admin/elements/_add_picture.html.erb +14 -0
- data/app/views/alchemy/admin/elements/_element.html.erb +23 -0
- data/app/views/alchemy/admin/elements/_element_foot.html.erb +36 -0
- data/app/views/alchemy/admin/elements/_element_head.html.erb +23 -0
- data/app/views/alchemy/admin/elements/_new_element_form.html.erb +26 -0
- data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +24 -0
- data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +8 -0
- data/app/views/alchemy/admin/elements/create.js.erb +46 -0
- data/app/views/alchemy/admin/elements/fold.js.erb +28 -0
- data/app/views/alchemy/admin/elements/index.html.erb +26 -0
- data/app/views/alchemy/admin/elements/list.html.erb +16 -0
- data/app/views/alchemy/admin/elements/new.html.erb +25 -0
- data/app/views/alchemy/admin/elements/order.js.erb +14 -0
- data/app/views/alchemy/admin/elements/trash.js.erb +12 -0
- data/app/views/alchemy/admin/elements/update.js.erb +28 -0
- data/app/views/alchemy/admin/essence_files/assign.js.erb +9 -0
- data/app/views/alchemy/admin/essence_files/edit.html.erb +18 -0
- data/app/views/alchemy/admin/essence_pictures/assign.js.erb +18 -0
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +50 -0
- data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +24 -0
- data/app/views/alchemy/admin/essence_pictures/edit.html.erb +28 -0
- data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +3 -0
- data/app/views/alchemy/admin/essence_pictures/update.js.erb +9 -0
- data/app/views/alchemy/admin/languages/_form.html.erb +14 -0
- data/app/views/alchemy/admin/languages/_language.html.erb +42 -0
- data/app/views/alchemy/admin/languages/_table.html.erb +37 -0
- data/app/views/alchemy/admin/languages/index.html.erb +23 -0
- data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +63 -0
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +15 -0
- data/app/views/alchemy/admin/layoutpages/index.html.erb +41 -0
- data/app/views/alchemy/admin/leave.html.erb +11 -0
- data/app/views/alchemy/admin/legacy_page_urls/_form.html.erb +5 -0
- data/app/views/alchemy/admin/legacy_page_urls/_label.html.erb +1 -0
- data/app/views/alchemy/admin/legacy_page_urls/_legacy_page_url.html.erb +13 -0
- data/app/views/alchemy/admin/legacy_page_urls/_new.html.erb +20 -0
- data/app/views/alchemy/admin/legacy_page_urls/create.js.erb +10 -0
- data/app/views/alchemy/admin/legacy_page_urls/destroy.js.erb +6 -0
- data/app/views/alchemy/admin/legacy_page_urls/update.js.erb +2 -0
- data/app/views/alchemy/admin/pages/_create_language_form.html.erb +54 -0
- data/app/views/alchemy/admin/pages/_external_link.html.erb +31 -0
- data/app/views/alchemy/admin/pages/_file_link.html.erb +31 -0
- data/app/views/alchemy/admin/pages/_form.html.erb +62 -0
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +41 -0
- data/app/views/alchemy/admin/pages/_legacy_urls.html.erb +23 -0
- data/app/views/alchemy/admin/pages/_locked_page.html.erb +24 -0
- data/app/views/alchemy/admin/pages/_new_page_form.html.erb +11 -0
- data/app/views/alchemy/admin/pages/_page.html.erb +112 -0
- data/app/views/alchemy/admin/pages/_page_for_links.html.erb +45 -0
- data/app/views/alchemy/admin/pages/_page_status.html.erb +14 -0
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +8 -0
- data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +13 -0
- data/app/views/alchemy/admin/pages/configure.html.erb +16 -0
- data/app/views/alchemy/admin/pages/configure_external.html.erb +33 -0
- data/app/views/alchemy/admin/pages/destroy.js.erb +19 -0
- data/app/views/alchemy/admin/pages/edit.html.erb +206 -0
- data/app/views/alchemy/admin/pages/flush.js.erb +2 -0
- data/app/views/alchemy/admin/pages/fold.js.erb +3 -0
- data/app/views/alchemy/admin/pages/index.html.erb +101 -0
- data/app/views/alchemy/admin/pages/info.html.erb +43 -0
- data/app/views/alchemy/admin/pages/link.html.erb +16 -0
- data/app/views/alchemy/admin/pages/locked.html.erb +3 -0
- data/app/views/alchemy/admin/pages/new.html.erb +26 -0
- data/app/views/alchemy/admin/pages/show.html.erb +1 -0
- data/app/views/alchemy/admin/pages/sort.js.erb +5 -0
- data/app/views/alchemy/admin/pages/unlock.js.erb +8 -0
- data/app/views/alchemy/admin/pages/update.js.erb +37 -0
- data/app/views/alchemy/admin/partials/_autocomplete_tag_list.html.erb +1 -0
- data/app/views/alchemy/admin/partials/_flash.html.erb +4 -0
- data/app/views/alchemy/admin/partials/_flash_notices.html.erb +5 -0
- data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +11 -0
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +12 -0
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +33 -0
- data/app/views/alchemy/admin/partials/_routes.html.erb +25 -0
- data/app/views/alchemy/admin/partials/_search_form.html.erb +20 -0
- data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
- data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
- data/app/views/alchemy/admin/partials/_upload_form.html.erb +67 -0
- data/app/views/alchemy/admin/pictures/_archive.html.erb +53 -0
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +14 -0
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +78 -0
- data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +33 -0
- data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +11 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +87 -0
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +28 -0
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +16 -0
- data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +8 -0
- data/app/views/alchemy/admin/pictures/edit.html.erb +13 -0
- data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +30 -0
- data/app/views/alchemy/admin/pictures/flush.js.erb +2 -0
- data/app/views/alchemy/admin/pictures/index.html.erb +109 -0
- data/app/views/alchemy/admin/pictures/index.js.erb +3 -0
- data/app/views/alchemy/admin/pictures/info.html.erb +38 -0
- data/app/views/alchemy/admin/pictures/new.html.erb +16 -0
- data/app/views/alchemy/admin/pictures/show.html.erb +11 -0
- data/app/views/alchemy/admin/resources/_form.html.erb +13 -0
- data/app/views/alchemy/admin/resources/_resource.html.erb +30 -0
- data/app/views/alchemy/admin/resources/_table.html.erb +25 -0
- data/app/views/alchemy/admin/resources/edit.html.erb +1 -0
- data/app/views/alchemy/admin/resources/index.csv.erb +13 -0
- data/app/views/alchemy/admin/resources/index.html.erb +32 -0
- data/app/views/alchemy/admin/resources/new.html.erb +1 -0
- data/app/views/alchemy/admin/sites/index.html.erb +23 -0
- data/app/views/alchemy/admin/tags/_radio_tag.html.erb +6 -0
- data/app/views/alchemy/admin/tags/_tag.html.erb +30 -0
- data/app/views/alchemy/admin/tags/edit.html.erb +24 -0
- data/app/views/alchemy/admin/tags/index.html.erb +52 -0
- data/app/views/alchemy/admin/tags/new.html.erb +7 -0
- data/app/views/alchemy/admin/trash/clear.js.erb +4 -0
- data/app/views/alchemy/admin/trash/index.html.erb +29 -0
- data/app/views/alchemy/attachments/show.html.erb +1 -0
- data/app/views/alchemy/base/500.html.erb +26 -0
- data/app/views/alchemy/base/error_notice.html.erb +1 -0
- data/app/views/alchemy/base/error_notice.js.erb +2 -0
- data/app/views/alchemy/base/permission_denied.js.erb +3 -0
- data/app/views/alchemy/base/redirect.js.erb +12 -0
- data/app/views/alchemy/base/update.js.erb +5 -0
- data/app/views/alchemy/breadcrumb/_page.html.erb +16 -0
- data/app/views/alchemy/breadcrumb/_separator.html.erb +1 -0
- data/app/views/alchemy/breadcrumb/_wrapper.html.erb +13 -0
- data/app/views/alchemy/elements/_editor_not_found.html.erb +5 -0
- data/app/views/alchemy/elements/_view_not_found.html.erb +1 -0
- data/app/views/alchemy/elements/show.html.erb +1 -0
- data/app/views/alchemy/elements/show.js.erb +1 -0
- data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +16 -0
- data/app/views/alchemy/essences/_essence_boolean_view.html.erb +3 -0
- data/app/views/alchemy/essences/_essence_date_editor.html.erb +19 -0
- data/app/views/alchemy/essences/_essence_date_view.html.erb +11 -0
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +57 -0
- data/app/views/alchemy/essences/_essence_file_view.html.erb +10 -0
- data/app/views/alchemy/essences/_essence_html_editor.html.erb +9 -0
- data/app/views/alchemy/essences/_essence_html_view.html.erb +3 -0
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +25 -0
- data/app/views/alchemy/essences/_essence_link_view.html.erb +11 -0
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +59 -0
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -0
- data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +13 -0
- data/app/views/alchemy/essences/_essence_richtext_view.html.erb +5 -0
- data/app/views/alchemy/essences/_essence_select_editor.html.erb +25 -0
- data/app/views/alchemy/essences/_essence_select_view.html.erb +3 -0
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -0
- data/app/views/alchemy/essences/_essence_text_view.html.erb +18 -0
- data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +61 -0
- data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +19 -0
- data/app/views/alchemy/language_links/_language.html.erb +12 -0
- data/app/views/alchemy/language_links/_spacer.html.erb +1 -0
- data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
- data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
- data/app/views/alchemy/messages/contact_form_mail.es.text.erb +12 -0
- data/app/views/alchemy/messages/new.html.erb +1 -0
- data/app/views/alchemy/navigation/_image_link.html.erb +14 -0
- data/app/views/alchemy/navigation/_link.html.erb +20 -0
- data/app/views/alchemy/navigation/_renderer.html.erb +30 -0
- data/app/views/alchemy/pages/show.html.erb +1 -0
- data/app/views/alchemy/pages/show.rss.builder +20 -0
- data/app/views/alchemy/pages/sitemap.xml.erb +6 -0
- data/app/views/kaminari/alchemy/_first_page.html.erb +11 -0
- data/app/views/kaminari/alchemy/_gap.html.erb +8 -0
- data/app/views/kaminari/alchemy/_last_page.html.erb +11 -0
- data/app/views/kaminari/alchemy/_next_page.html.erb +13 -0
- data/app/views/kaminari/alchemy/_page.html.erb +14 -0
- data/app/views/kaminari/alchemy/_paginator.html.erb +23 -0
- data/app/views/kaminari/alchemy/_prev_page.html.erb +13 -0
- data/app/views/layouts/alchemy/admin.html.erb +109 -0
- data/app/views/layouts/alchemy/sitemap.xml.erb +4 -0
- data/bin/alchemy +267 -0
- data/bin/rails +8 -0
- data/config/alchemy/config.yml +189 -0
- data/config/alchemy/modules.yml +88 -0
- data/config/initializers/dragonfly.rb +25 -0
- data/config/initializers/simple_form.rb +144 -0
- data/config/locales/alchemy.de.yml +918 -0
- data/config/locales/alchemy.en.yml +920 -0
- data/config/locales/alchemy.es.yml +958 -0
- data/config/locales/alchemy.fr.yml +942 -0
- data/config/locales/alchemy.nl.yml +921 -0
- data/config/locales/alchemy.ru.yml +837 -0
- data/config/locales/simple_form.de.yml +26 -0
- data/config/locales/simple_form.en.yml +25 -0
- data/config/locales/simple_form.es.yml +6 -0
- data/config/locales/simple_form.fr.yml +26 -0
- data/config/locales/simple_form.nl.yml +25 -0
- data/config/locales/simple_form.ru.yml +25 -0
- data/config/routes.rb +164 -0
- data/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
- data/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
- data/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
- data/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
- data/lib/alchemy/auth_accessors.rb +104 -0
- data/lib/alchemy/cache_digests/template_tracker.rb +65 -0
- data/lib/alchemy/config.rb +65 -0
- data/lib/alchemy/configuration_methods.rb +29 -0
- data/lib/alchemy/controller_actions.rb +138 -0
- data/lib/alchemy/engine.rb +104 -0
- data/lib/alchemy/errors.rb +82 -0
- data/lib/alchemy/essence.rb +232 -0
- data/lib/alchemy/filetypes.rb +33 -0
- data/lib/alchemy/forms/builder.rb +23 -0
- data/lib/alchemy/hints.rb +57 -0
- data/lib/alchemy/i18n.rb +70 -0
- data/lib/alchemy/kaminari/scoped_pagination_url_helper.rb +13 -0
- data/lib/alchemy/locale.rb +65 -0
- data/lib/alchemy/logger.rb +15 -0
- data/lib/alchemy/middleware/rescue_old_cookies.rb +27 -0
- data/lib/alchemy/modules.rb +75 -0
- data/lib/alchemy/mount_point.rb +47 -0
- data/lib/alchemy/name_conversions.rb +28 -0
- data/lib/alchemy/on_page_layout.rb +58 -0
- data/lib/alchemy/page_layout.rb +183 -0
- data/lib/alchemy/permissions.rb +221 -0
- data/lib/alchemy/picture_attributes.rb +29 -0
- data/lib/alchemy/resource.rb +238 -0
- data/lib/alchemy/resources_helper.rb +135 -0
- data/lib/alchemy/routing_constraints.rb +49 -0
- data/lib/alchemy/seeder.rb +53 -0
- data/lib/alchemy/shell.rb +102 -0
- data/lib/alchemy/ssl_protection.rb +30 -0
- data/lib/alchemy/tasks/helpers.rb +83 -0
- data/lib/alchemy/test_support/controller_requests.rb +73 -0
- data/lib/alchemy/test_support/essence_shared_examples.rb +286 -0
- data/lib/alchemy/test_support/factories.rb +147 -0
- data/lib/alchemy/test_support/integration_helpers.rb +33 -0
- data/lib/alchemy/tinymce.rb +68 -0
- data/lib/alchemy/touching.rb +41 -0
- data/lib/alchemy/upgrader.rb +80 -0
- data/lib/alchemy/upgrader/three_point_one.rb +54 -0
- data/lib/alchemy/upgrader/three_point_two.rb +69 -0
- data/lib/alchemy/upgrader/three_point_zero.rb +93 -0
- data/lib/alchemy/userstamp.rb +10 -0
- data/lib/alchemy/version.rb +7 -0
- data/lib/alchemy_cms.rb +5 -0
- data/lib/rails/generators/alchemy/base.rb +41 -0
- data/lib/rails/generators/alchemy/elements/elements_generator.rb +37 -0
- data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +14 -0
- data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +13 -0
- data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +12 -0
- data/lib/rails/generators/alchemy/elements/templates/view.html.erb +27 -0
- data/lib/rails/generators/alchemy/elements/templates/view.html.haml +20 -0
- data/lib/rails/generators/alchemy/elements/templates/view.html.slim +20 -0
- data/lib/rails/generators/alchemy/essence/essence_generator.rb +52 -0
- data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +17 -0
- data/lib/rails/generators/alchemy/essence/templates/view.html.erb +2 -0
- data/lib/rails/generators/alchemy/install/files/_article_editor.html.erb +5 -0
- data/lib/rails/generators/alchemy/install/files/_article_view.html.erb +7 -0
- data/lib/rails/generators/alchemy/install/files/_standard.html.erb +1 -0
- data/lib/rails/generators/alchemy/install/files/alchemy.de.yml +31 -0
- data/lib/rails/generators/alchemy/install/files/alchemy.elements.css.scss +30 -0
- data/lib/rails/generators/alchemy/install/files/alchemy.en.yml +31 -0
- data/lib/rails/generators/alchemy/install/files/alchemy.es.yml +31 -0
- data/lib/rails/generators/alchemy/install/files/application.html.erb +14 -0
- data/lib/rails/generators/alchemy/install/install_generator.rb +69 -0
- data/lib/rails/generators/alchemy/install/templates/elements.yml.tt +21 -0
- data/lib/rails/generators/alchemy/install/templates/page_layouts.yml.tt +10 -0
- data/lib/rails/generators/alchemy/module/module_generator.rb +30 -0
- data/lib/rails/generators/alchemy/module/templates/ability.rb.tt +11 -0
- data/lib/rails/generators/alchemy/module/templates/controller.rb.tt +2 -0
- data/lib/rails/generators/alchemy/module/templates/module_config.rb.tt +17 -0
- data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +24 -0
- data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.erb +1 -0
- data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.haml +1 -0
- data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.slim +1 -0
- data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
- data/lib/rails/generators/alchemy/views/views_generator.rb +41 -0
- data/lib/rails/templates/alchemy.rb +7 -0
- data/lib/tasks/alchemy/convert.rake +39 -0
- data/lib/tasks/alchemy/db.rake +22 -0
- data/lib/tasks/alchemy/install.rake +61 -0
- data/lib/tasks/alchemy/tidy.rake +102 -0
- data/lib/tasks/alchemy/upgrade.rake +28 -0
- data/spec/controllers/admin/attachments_controller_spec.rb +211 -0
- data/spec/controllers/admin/base_controller_spec.rb +74 -0
- data/spec/controllers/admin/clipboard_controller_spec.rb +60 -0
- data/spec/controllers/admin/contents_controller_spec.rb +72 -0
- data/spec/controllers/admin/dashboard_controller_spec.rb +139 -0
- data/spec/controllers/admin/elements_controller_spec.rb +473 -0
- data/spec/controllers/admin/essence_files_controller_spec.rb +71 -0
- data/spec/controllers/admin/essence_pictures_controller_spec.rb +202 -0
- data/spec/controllers/admin/languages_controller_spec.rb +61 -0
- data/spec/controllers/admin/layoutpages_controller_spec.rb +27 -0
- data/spec/controllers/admin/pages_controller_spec.rb +553 -0
- data/spec/controllers/admin/pictures_controller_spec.rb +358 -0
- data/spec/controllers/admin/resources_controller_spec.rb +53 -0
- data/spec/controllers/admin/trash_controller_spec.rb +68 -0
- data/spec/controllers/alchemy/admin/tags_controller_spec.rb +63 -0
- data/spec/controllers/alchemy/api/contents_controller_spec.rb +126 -0
- data/spec/controllers/alchemy/api/elements_controller_spec.rb +125 -0
- data/spec/controllers/alchemy/api/pages_controller_spec.rb +134 -0
- data/spec/controllers/attachments_controller_spec.rb +64 -0
- data/spec/controllers/base_controller_spec.rb +51 -0
- data/spec/controllers/elements_controller_spec.rb +48 -0
- data/spec/controllers/messages_controller_spec.rb +199 -0
- data/spec/controllers/pages_controller_spec.rb +265 -0
- data/spec/controllers/pictures_controller_spec.rb +393 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/admin/events_controller.rb +3 -0
- data/spec/dummy/app/controllers/application_controller.rb +15 -0
- data/spec/dummy/app/controllers/login_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/ability.rb +9 -0
- data/spec/dummy/app/models/dummy_model.rb +3 -0
- data/spec/dummy/app/models/dummy_user.rb +11 -0
- data/spec/dummy/app/models/event.rb +10 -0
- data/spec/dummy/app/models/location.rb +3 -0
- data/spec/dummy/app/views/alchemy/elements/_all_you_can_eat_editor.html.erb +11 -0
- data/spec/dummy/app/views/alchemy/elements/_article_editor.html.erb +10 -0
- data/spec/dummy/app/views/alchemy/elements/_article_view.html.erb +25 -0
- data/spec/dummy/app/views/alchemy/elements/_headline_editor.html.erb +1 -0
- data/spec/dummy/app/views/alchemy/elements/_headline_view.html.erb +1 -0
- data/spec/dummy/app/views/alchemy/elements/_news_view.html.erb +11 -0
- data/spec/dummy/app/views/alchemy/page_layouts/_standard.html.erb +14 -0
- data/spec/dummy/app/views/layouts/application.html.erb +17 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/alchemy/cells.yml +5 -0
- data/spec/dummy/config/alchemy/elements.yml +112 -0
- data/spec/dummy/config/alchemy/page_layouts.yml +32 -0
- data/spec/dummy/config/application.rb +32 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +77 -0
- data/spec/dummy/config/environments/test.rb +43 -0
- data/spec/dummy/config/initializers/alchemy.rb +2 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/routes.rb +12 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/migrate/20121026104128_create_events.rb +20 -0
- data/spec/dummy/db/migrate/20130328101418_create_locations.rb +9 -0
- data/spec/dummy/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
- data/spec/dummy/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
- data/spec/dummy/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
- data/spec/dummy/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
- data/spec/dummy/db/migrate/20131209225243_create_dummy_users.rb +9 -0
- data/spec/dummy/db/migrate/20150122213511_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +31 -0
- data/spec/dummy/db/migrate/20150122213512_add_missing_unique_indices.acts_as_taggable_on_engine.rb +20 -0
- data/spec/dummy/db/migrate/20150122213513_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
- data/spec/dummy/db/migrate/20150122213514_add_missing_taggable_index.acts_as_taggable_on_engine.rb +10 -0
- data/spec/dummy/db/migrate/20150412103152_create_dummy_model.rb +7 -0
- data/spec/dummy/db/schema.rb +322 -0
- data/spec/dummy/db/seeds.rb +1 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/features/admin/dashboard_spec.rb +82 -0
- data/spec/features/admin/language_tree_feature_spec.rb +33 -0
- data/spec/features/admin/legacy_page_url_management_spec.rb +62 -0
- data/spec/features/admin/link_overlay_spec.rb +54 -0
- data/spec/features/admin/locale_select_feature_spec.rb +25 -0
- data/spec/features/admin/modules_integration_spec.rb +24 -0
- data/spec/features/admin/navigation_feature_spec.rb +13 -0
- data/spec/features/admin/page_creation_feature_spec.rb +51 -0
- data/spec/features/admin/page_editing_feature_spec.rb +135 -0
- data/spec/features/admin/picture_library_integration_spec.rb +62 -0
- data/spec/features/admin/resources_integration_spec.rb +133 -0
- data/spec/features/admin/site_select_feature_spec.rb +32 -0
- data/spec/features/admin/tinymce_feature_spec.rb +34 -0
- data/spec/features/navigation_spec.rb +9 -0
- data/spec/features/page_feature_spec.rb +287 -0
- data/spec/features/picture_security_spec.rb +35 -0
- data/spec/features/security_spec.rb +24 -0
- data/spec/features/translation_integration_spec.rb +51 -0
- data/spec/fixtures/500x500.png +0 -0
- data/spec/fixtures/80x60.png +0 -0
- data/spec/fixtures/image with spaces.png +0 -0
- data/spec/fixtures/image.png +0 -0
- data/spec/fixtures/image2.PNG +0 -0
- data/spec/fixtures/image3.jpeg +0 -0
- data/spec/helpers/admin/attachments_helper_spec.rb +15 -0
- data/spec/helpers/admin/base_helper_spec.rb +270 -0
- data/spec/helpers/admin/contents_helper_spec.rb +65 -0
- data/spec/helpers/admin/elements_helper_spec.rb +178 -0
- data/spec/helpers/admin/essences_helper_spec.rb +140 -0
- data/spec/helpers/admin/navigation_helper_spec.rb +288 -0
- data/spec/helpers/admin/pages_helper_spec.rb +95 -0
- data/spec/helpers/admin/pictures_helper_spec.rb +29 -0
- data/spec/helpers/admin/tags_helper_spec.rb +113 -0
- data/spec/helpers/base_helper_spec.rb +45 -0
- data/spec/helpers/elements_block_helper_spec.rb +135 -0
- data/spec/helpers/elements_helper_spec.rb +311 -0
- data/spec/helpers/essences_helper_spec.rb +156 -0
- data/spec/helpers/pages_helper_spec.rb +413 -0
- data/spec/helpers/picture_url_helpers_spec.rb +35 -0
- data/spec/helpers/url_helper_spec.rb +174 -0
- data/spec/javascripts/alchemy/dialog_spec.coffee +82 -0
- data/spec/javascripts/alchemy/link_overlay_spec.coffee +25 -0
- data/spec/javascripts/alchemy_integration_spec.coffee +3 -0
- data/spec/javascripts/fixtures/select.html +3 -0
- data/spec/javascripts/helpers/mock-ajax.js +199 -0
- data/spec/javascripts/helpers/test_responses/test_responses.js +1 -0
- data/spec/javascripts/support/jasmine.yml +29 -0
- data/spec/libraries/auth_accessors_spec.rb +40 -0
- data/spec/libraries/config_spec.rb +112 -0
- data/spec/libraries/controller_actions_spec.rb +133 -0
- data/spec/libraries/i18n_spec.rb +30 -0
- data/spec/libraries/kaminari/scoped_pagination_url_helper_spec.rb +30 -0
- data/spec/libraries/modules_spec.rb +67 -0
- data/spec/libraries/mount_point_spec.rb +77 -0
- data/spec/libraries/on_page_layout_spec.rb +112 -0
- data/spec/libraries/page_layout_spec.rb +144 -0
- data/spec/libraries/permissions_spec.rb +261 -0
- data/spec/libraries/resource_spec.rb +371 -0
- data/spec/libraries/resources_helper_spec.rb +144 -0
- data/spec/libraries/shell_spec.rb +125 -0
- data/spec/libraries/template_tracker_spec.rb +94 -0
- data/spec/libraries/tinymce_spec.rb +67 -0
- data/spec/libraries/userstamp_spec.rb +10 -0
- data/spec/mailers/messages_spec.rb +23 -0
- data/spec/models/attachment_spec.rb +227 -0
- data/spec/models/cell_spec.rb +102 -0
- data/spec/models/content_spec.rb +404 -0
- data/spec/models/dummy_model_spec.rb +11 -0
- data/spec/models/element_spec.rb +617 -0
- data/spec/models/element_to_page_spec.rb +14 -0
- data/spec/models/essence_boolean_spec.rb +10 -0
- data/spec/models/essence_date_spec.rb +29 -0
- data/spec/models/essence_file_spec.rb +43 -0
- data/spec/models/essence_html_spec.rb +18 -0
- data/spec/models/essence_link_spec.rb +10 -0
- data/spec/models/essence_picture_spec.rb +183 -0
- data/spec/models/essence_richtext_spec.rb +18 -0
- data/spec/models/essence_select_spec.rb +10 -0
- data/spec/models/essence_text_spec.rb +114 -0
- data/spec/models/language_spec.rb +123 -0
- data/spec/models/legacy_page_url_spec.rb +21 -0
- data/spec/models/message_spec.rb +55 -0
- data/spec/models/page_spec.rb +1896 -0
- data/spec/models/picture_spec.rb +330 -0
- data/spec/models/site_spec.rb +233 -0
- data/spec/models/tag_spec.rb +31 -0
- data/spec/routing/api_routing_spec.rb +150 -0
- data/spec/routing/routing_spec.rb +234 -0
- data/spec/spec_helper.rb +89 -0
- data/spec/support/ci/install_phantomjs +7 -0
- data/spec/support/hint_examples.rb +30 -0
- data/spec/support/rspec-activemodel-mocks_patch.rb +8 -0
- data/spec/support/test_tweaks.rb +31 -0
- data/spec/support/transformation_examples.rb +180 -0
- data/spec/tasks/helpers_spec.rb +219 -0
- data/spec/views/essences/essence_boolean_editor_spec.rb +33 -0
- data/spec/views/essences/essence_boolean_view_spec.rb +25 -0
- data/spec/views/essences/essence_date_view_spec.rb +39 -0
- data/spec/views/essences/essence_file_editor_spec.rb +61 -0
- data/spec/views/essences/essence_file_view_spec.rb +24 -0
- data/spec/views/essences/essence_html_view_spec.rb +22 -0
- data/spec/views/essences/essence_link_view_spec.rb +41 -0
- data/spec/views/essences/essence_picture_view_spec.rb +129 -0
- data/spec/views/essences/essence_richtext_view_spec.rb +32 -0
- data/spec/views/essences/essence_select_view_spec.rb +12 -0
- data/spec/views/essences/essence_text_view_spec.rb +52 -0
- data/vendor/assets/images/Jcrop.gif +0 -0
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +175 -0
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +122 -0
- data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +1467 -0
- data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +217 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +22 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.floatThead.min.js +3 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js +7 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +435 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +296 -0
- data/vendor/assets/javascripts/keymaster.js +296 -0
- data/vendor/assets/javascripts/requestAnimationFrame.js +31 -0
- data/vendor/assets/javascripts/spin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/langs/de.js +200 -0
- data/vendor/assets/javascripts/tinymce/langs/es.js +200 -0
- data/vendor/assets/javascripts/tinymce/langs/fr.js +200 -0
- data/vendor/assets/javascripts/tinymce/langs/nl.js +200 -0
- data/vendor/assets/javascripts/tinymce/langs/ru.js +200 -0
- data/vendor/assets/javascripts/tinymce/license.txt +504 -0
- data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +1 -0
- data/vendor/assets/javascripts/tinymce/tinymce.min.js +13 -0
- data/vendor/assets/stylesheets/jquery.Jcrop.min.css +28 -0
- metadata +1453 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
module Alchemy
|
|
2
|
+
|
|
3
|
+
# Holds everything concerning the building and creating of contents and the related essence object.
|
|
4
|
+
#
|
|
5
|
+
module Content::Factory
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
SKIPPED_ATTRIBUTES_ON_COPY = %w(position created_at updated_at creator_id updater_id id)
|
|
10
|
+
|
|
11
|
+
# Builds a new content as descriped in the elements.yml file.
|
|
12
|
+
#
|
|
13
|
+
# @param [Alchemy::Element]
|
|
14
|
+
# The element the content is for
|
|
15
|
+
# @param [Hash]
|
|
16
|
+
# The content description used for finding the content in +elements.yml+ file
|
|
17
|
+
#
|
|
18
|
+
def build(element, essence_hash)
|
|
19
|
+
if (description = content_description(element, essence_hash)).blank?
|
|
20
|
+
raise ContentDefinitionError, "No description found in elements.yml for #{essence_hash.inspect} and #{element.inspect}"
|
|
21
|
+
else
|
|
22
|
+
new(name: description['name'], element_id: element.id)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Creates a new content from elements description in the +elements.yml+ file.
|
|
27
|
+
#
|
|
28
|
+
# 1. It builds the content
|
|
29
|
+
# 2. It creates the essence record (content object gets saved)
|
|
30
|
+
#
|
|
31
|
+
# @return [Alchemy::Content]
|
|
32
|
+
#
|
|
33
|
+
def create_from_scratch(element, essence_hash)
|
|
34
|
+
essence_hash.stringify_keys!
|
|
35
|
+
if content = build(element, essence_hash)
|
|
36
|
+
content.create_essence!(essence_hash['essence_type'])
|
|
37
|
+
end
|
|
38
|
+
content
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Makes a copy of source and also copies the associated essence.
|
|
42
|
+
#
|
|
43
|
+
# You can pass a differences hash to update the attributes of the copy.
|
|
44
|
+
#
|
|
45
|
+
# === Example
|
|
46
|
+
#
|
|
47
|
+
# @copy = Alchemy::Content.copy(@content, {:element_id => 3})
|
|
48
|
+
# @copy.element_id # => 3
|
|
49
|
+
#
|
|
50
|
+
def copy(source, differences = {})
|
|
51
|
+
attributes = source.attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY).merge(differences.stringify_keys)
|
|
52
|
+
content = self.create!(attributes)
|
|
53
|
+
new_essence = content.essence.class.new(content.essence.attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY))
|
|
54
|
+
new_essence.save!
|
|
55
|
+
raise "Essence not cloned" if new_essence.id == content.essence_id
|
|
56
|
+
content.update_attributes(essence_id: new_essence.id)
|
|
57
|
+
content
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the content description for building a content.
|
|
61
|
+
#
|
|
62
|
+
# 1. It looks in the element's contents description
|
|
63
|
+
# 2. It builds a description hash from essence type, if the the name key is not present
|
|
64
|
+
#
|
|
65
|
+
def content_description(element, essence_hash)
|
|
66
|
+
essence_hash.stringify_keys!
|
|
67
|
+
# No name given. We build the content from essence type.
|
|
68
|
+
if essence_hash['name'].blank? && essence_hash['essence_type'].present?
|
|
69
|
+
content_description_from_essence_type(element, essence_hash['essence_type'])
|
|
70
|
+
else
|
|
71
|
+
content_description_from_element(element, essence_hash['name'])
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Returns a hash for building a content from essence type.
|
|
76
|
+
#
|
|
77
|
+
# @param [Alchemy::Element]
|
|
78
|
+
# The element the content is for.
|
|
79
|
+
# @param [String]
|
|
80
|
+
# The essence type the content is from
|
|
81
|
+
#
|
|
82
|
+
def content_description_from_essence_type(element, essence_type)
|
|
83
|
+
{
|
|
84
|
+
'type' => essence_type,
|
|
85
|
+
'name' => content_name_from_element_and_essence_type(element, essence_type)
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# A name for content from its essence type and amount of same essences in element.
|
|
90
|
+
#
|
|
91
|
+
# Example:
|
|
92
|
+
#
|
|
93
|
+
# essence_picture_1
|
|
94
|
+
#
|
|
95
|
+
def content_name_from_element_and_essence_type(element, essence_type)
|
|
96
|
+
essences_of_same_type = element.contents.where(essence_type: normalize_essence_type(essence_type))
|
|
97
|
+
"#{essence_type.classify.demodulize.underscore}_#{essences_of_same_type.count + 1}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns the content description hash from element.
|
|
101
|
+
#
|
|
102
|
+
# It first uses the normal content description described in the +elements.yml+ +contents+ array.
|
|
103
|
+
#
|
|
104
|
+
# If the content description could not be found it tries to load it from +available_contents+ array.
|
|
105
|
+
#
|
|
106
|
+
# @param [Alchemy::Element]
|
|
107
|
+
# The element instance the content is for
|
|
108
|
+
# @param [String]
|
|
109
|
+
# The name of the content
|
|
110
|
+
#
|
|
111
|
+
def content_description_from_element(element, name)
|
|
112
|
+
element.content_description_for(name) ||
|
|
113
|
+
element.available_content_description_for(name)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Returns all content descriptions from elements.yml
|
|
117
|
+
#
|
|
118
|
+
def descriptions
|
|
119
|
+
Element.descriptions.collect { |e| e['contents'] }.flatten.compact
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Returns a normalized Essence type
|
|
123
|
+
#
|
|
124
|
+
# Adds Alchemy module name in front of given essence type
|
|
125
|
+
# unless there is a Class with the specified name that is an essence.
|
|
126
|
+
#
|
|
127
|
+
# @param [String]
|
|
128
|
+
# the essence type to normalize
|
|
129
|
+
#
|
|
130
|
+
def normalize_essence_type(essence_type)
|
|
131
|
+
essence_type = essence_type.classify
|
|
132
|
+
return essence_type if is_an_essence?(essence_type)
|
|
133
|
+
|
|
134
|
+
"Alchemy::#{essence_type}"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def is_an_essence?(essence_type)
|
|
140
|
+
klass = Module.const_get(essence_type)
|
|
141
|
+
klass.is_a?(Class) && klass.new.acts_as_essence?
|
|
142
|
+
rescue NameError
|
|
143
|
+
false
|
|
144
|
+
end
|
|
145
|
+
end # end class methods
|
|
146
|
+
|
|
147
|
+
# Instance Methods
|
|
148
|
+
|
|
149
|
+
# Returns the description hash from +elements.yml+ file.
|
|
150
|
+
#
|
|
151
|
+
def description
|
|
152
|
+
if element.blank?
|
|
153
|
+
log_warning "Content with id #{self.id} is missing its Element."
|
|
154
|
+
return {}
|
|
155
|
+
end
|
|
156
|
+
Content.content_description_from_element(element, name) || {}
|
|
157
|
+
end
|
|
158
|
+
alias_method :definition, :description
|
|
159
|
+
|
|
160
|
+
# Creates essence from description.
|
|
161
|
+
#
|
|
162
|
+
# If an optional type is passed, this type of essence gets created.
|
|
163
|
+
#
|
|
164
|
+
def create_essence!(type = nil)
|
|
165
|
+
self.essence = essence_class(type).create!(prepared_attributes_for_essence)
|
|
166
|
+
self.save!
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
# Returns a class constant from description's type field.
|
|
172
|
+
#
|
|
173
|
+
# If an optional type is passed, this type of essence gets constantized.
|
|
174
|
+
#
|
|
175
|
+
def essence_class(type = nil)
|
|
176
|
+
Content.normalize_essence_type(type || description['type']).constantize
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Prepares the attributes for creating the essence.
|
|
180
|
+
#
|
|
181
|
+
# 1. It sets a default text if given in +elements.yml+
|
|
182
|
+
#
|
|
183
|
+
def prepared_attributes_for_essence
|
|
184
|
+
attributes = {
|
|
185
|
+
ingredient: default_text(description['default'])
|
|
186
|
+
}
|
|
187
|
+
attributes
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Table name: alchemy_elements
|
|
4
|
+
#
|
|
5
|
+
# id :integer not null, primary key
|
|
6
|
+
# name :string(255)
|
|
7
|
+
# position :integer
|
|
8
|
+
# page_id :integer
|
|
9
|
+
# public :boolean default(TRUE)
|
|
10
|
+
# folded :boolean default(FALSE)
|
|
11
|
+
# unique :boolean default(FALSE)
|
|
12
|
+
# created_at :datetime not null
|
|
13
|
+
# updated_at :datetime not null
|
|
14
|
+
# creator_id :integer
|
|
15
|
+
# updater_id :integer
|
|
16
|
+
# cell_id :integer
|
|
17
|
+
# cached_tag_list :text
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Alchemy
|
|
21
|
+
class Element < ActiveRecord::Base
|
|
22
|
+
include Alchemy::Logger
|
|
23
|
+
include Alchemy::Touching
|
|
24
|
+
include Alchemy::Hints
|
|
25
|
+
|
|
26
|
+
FORBIDDEN_DEFINITION_ATTRIBUTES = %w(contents available_contents amount picture_gallery taggable hint)
|
|
27
|
+
SKIPPED_ATTRIBUTES_ON_COPY = %w(id position folded created_at updated_at creator_id updater_id cached_tag_list)
|
|
28
|
+
|
|
29
|
+
acts_as_taggable
|
|
30
|
+
|
|
31
|
+
# All Elements inside a cell are a list. All Elements not in cell are in the cell_id.nil list.
|
|
32
|
+
acts_as_list scope: [:page_id, :cell_id]
|
|
33
|
+
stampable stamper_class_name: Alchemy.user_class_name
|
|
34
|
+
|
|
35
|
+
has_many :contents, -> { order(:position) }, dependent: :destroy
|
|
36
|
+
belongs_to :cell
|
|
37
|
+
belongs_to :page
|
|
38
|
+
has_and_belongs_to_many :touchable_pages, -> { uniq },
|
|
39
|
+
class_name: 'Alchemy::Page',
|
|
40
|
+
join_table: ElementToPage.table_name
|
|
41
|
+
|
|
42
|
+
validates_presence_of :name, :on => :create
|
|
43
|
+
validates_format_of :name, :on => :create, :with => /\A[a-z0-9_-]+\z/
|
|
44
|
+
|
|
45
|
+
attr_accessor :create_contents_after_create
|
|
46
|
+
|
|
47
|
+
after_create :create_contents, :unless => proc { |e| e.create_contents_after_create == false }
|
|
48
|
+
after_update :touch_pages
|
|
49
|
+
after_update :touch_cell, unless: -> { self.cell.nil? }
|
|
50
|
+
|
|
51
|
+
scope :trashed, -> { where(position: nil).order('updated_at DESC') }
|
|
52
|
+
scope :not_trashed, -> { where(Element.arel_table[:position].not_eq(nil)) }
|
|
53
|
+
scope :published, -> { where(public: true) }
|
|
54
|
+
scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
|
|
55
|
+
scope :available, -> { published.not_trashed }
|
|
56
|
+
scope :named, ->(names) { where(name: names) }
|
|
57
|
+
scope :excluded, ->(names) { where(arel_table[:name].not_in(names)) }
|
|
58
|
+
scope :not_in_cell, -> { where(cell_id: nil) }
|
|
59
|
+
scope :in_cell, -> { where("#{self.table_name}.cell_id IS NOT NULL") }
|
|
60
|
+
scope :from_current_site, -> { where(Language.table_name => {site_id: Site.current || Site.default}).joins(page: 'language') }
|
|
61
|
+
|
|
62
|
+
delegate :restricted?, to: :page, allow_nil: true
|
|
63
|
+
|
|
64
|
+
# Concerns
|
|
65
|
+
include Alchemy::Element::Definitions
|
|
66
|
+
include Alchemy::Element::Presenters
|
|
67
|
+
|
|
68
|
+
# class methods
|
|
69
|
+
class << self
|
|
70
|
+
|
|
71
|
+
# Builds a new element as described in +/config/alchemy/elements.yml+
|
|
72
|
+
#
|
|
73
|
+
# - Returns a new Alchemy::Element object if no name is given in attributes,
|
|
74
|
+
# because the definition can not be found w/o name
|
|
75
|
+
# - Raises Alchemy::ElementDefinitionError if no definition for given attributes[:name]
|
|
76
|
+
# could be found
|
|
77
|
+
#
|
|
78
|
+
def new_from_scratch(attributes = {})
|
|
79
|
+
attributes = attributes.dup.symbolize_keys
|
|
80
|
+
|
|
81
|
+
return new if attributes[:name].blank?
|
|
82
|
+
|
|
83
|
+
new_element_from_definition_by(attributes) ||
|
|
84
|
+
raise(ElementDefinitionError.new(attributes))
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Creates a new element as described in +/config/alchemy/elements.yml+
|
|
88
|
+
#
|
|
89
|
+
# - Returns a new Alchemy::Element object if no name is given in attributes,
|
|
90
|
+
# because the definition can not be found w/o name
|
|
91
|
+
# - Raises Alchemy::ElementDefinitionError if no definition for given attributes[:name]
|
|
92
|
+
# could be found
|
|
93
|
+
#
|
|
94
|
+
def create_from_scratch(attributes)
|
|
95
|
+
element = new_from_scratch(attributes)
|
|
96
|
+
element.save if element
|
|
97
|
+
element
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# This methods does a copy of source and all depending contents and all of their depending essences.
|
|
101
|
+
#
|
|
102
|
+
# == Options
|
|
103
|
+
#
|
|
104
|
+
# You can pass a differences Hash as second option to update attributes for the copy.
|
|
105
|
+
#
|
|
106
|
+
# == Example
|
|
107
|
+
#
|
|
108
|
+
# @copy = Alchemy::Element.copy(@element, {:public => false})
|
|
109
|
+
# @copy.public? # => false
|
|
110
|
+
#
|
|
111
|
+
def copy(source, differences = {})
|
|
112
|
+
source.attributes.stringify_keys!
|
|
113
|
+
differences.stringify_keys!
|
|
114
|
+
attributes = source.attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY).merge(differences)
|
|
115
|
+
element = self.create!(attributes.merge(:create_contents_after_create => false))
|
|
116
|
+
element.tag_list = source.tag_list
|
|
117
|
+
source.contents.each do |content|
|
|
118
|
+
new_content = Content.copy(content, :element_id => element.id)
|
|
119
|
+
new_content.move_to_bottom
|
|
120
|
+
end
|
|
121
|
+
element
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def all_from_clipboard(clipboard)
|
|
125
|
+
return [] if clipboard.nil?
|
|
126
|
+
where(id: clipboard.collect { |e| e['id'] })
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# All elements in clipboard that could be placed on page
|
|
130
|
+
#
|
|
131
|
+
def all_from_clipboard_for_page(clipboard, page)
|
|
132
|
+
return [] if clipboard.nil? || page.nil?
|
|
133
|
+
all_from_clipboard(clipboard).select { |ce|
|
|
134
|
+
page.available_element_names.include?(ce.name)
|
|
135
|
+
}
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def new_element_from_definition_by(attributes)
|
|
141
|
+
remove_cell_name_from_element_name!(attributes)
|
|
142
|
+
|
|
143
|
+
element_scratch = definitions.detect { |el| el['name'] == attributes[:name] }
|
|
144
|
+
return if element_scratch.nil?
|
|
145
|
+
|
|
146
|
+
new(element_scratch.merge(attributes).except(*FORBIDDEN_DEFINITION_ATTRIBUTES))
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def remove_cell_name_from_element_name!(attributes)
|
|
150
|
+
attributes[:name] = attributes[:name].split('#').first
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Returns next public element from same page.
|
|
155
|
+
#
|
|
156
|
+
# Pass an element name to get next of this kind.
|
|
157
|
+
#
|
|
158
|
+
def next(name = nil)
|
|
159
|
+
previous_or_next('>', name)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Returns previous public element from same page.
|
|
163
|
+
#
|
|
164
|
+
# Pass an element name to get previous of this kind.
|
|
165
|
+
#
|
|
166
|
+
def prev(name = nil)
|
|
167
|
+
previous_or_next('<', name)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Stores the page into +touchable_pages+ (Pages that have to be touched after updating the element).
|
|
171
|
+
def store_page(page)
|
|
172
|
+
return true if page.nil?
|
|
173
|
+
unless self.touchable_pages.include? page
|
|
174
|
+
self.touchable_pages << page
|
|
175
|
+
self.save
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Trashing an element means nullifying its position, folding and unpublishing it.
|
|
180
|
+
def trash!
|
|
181
|
+
self.public = false
|
|
182
|
+
self.folded = true
|
|
183
|
+
self.remove_from_list
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def trashed?
|
|
187
|
+
self.position.nil?
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def content_by_name(name)
|
|
191
|
+
self.contents.find_by_name(name)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def content_by_type(essence_type)
|
|
195
|
+
self.contents.find_by_essence_type(Content.normalize_essence_type(essence_type))
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def all_contents_by_name(name)
|
|
199
|
+
self.contents.where(:name => name)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def all_contents_by_type(essence_type)
|
|
203
|
+
self.contents.where(:essence_type => Content.normalize_essence_type(essence_type))
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Returns the content that is marked as rss title.
|
|
207
|
+
#
|
|
208
|
+
# Mark a content as rss title in your +elements.yml+ file:
|
|
209
|
+
#
|
|
210
|
+
# - name: news
|
|
211
|
+
# contents:
|
|
212
|
+
# - name: headline
|
|
213
|
+
# type: EssenceText
|
|
214
|
+
# rss_title: true
|
|
215
|
+
#
|
|
216
|
+
def content_for_rss_title
|
|
217
|
+
content_for_rss_meta('title')
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Returns the content that is marked as rss description.
|
|
221
|
+
#
|
|
222
|
+
# Mark a content as rss description in your +elements.yml+ file:
|
|
223
|
+
#
|
|
224
|
+
# - name: news
|
|
225
|
+
# contents:
|
|
226
|
+
# - name: body
|
|
227
|
+
# type: EssenceRichtext
|
|
228
|
+
# rss_description: true
|
|
229
|
+
#
|
|
230
|
+
def content_for_rss_description
|
|
231
|
+
content_for_rss_meta('description')
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Returns the array with the hashes for all element contents in the elements.yml file
|
|
235
|
+
def content_descriptions
|
|
236
|
+
return nil if definition.blank?
|
|
237
|
+
definition['contents']
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Returns the definition for given content_name
|
|
241
|
+
def content_description_for(content_name)
|
|
242
|
+
if content_descriptions.blank?
|
|
243
|
+
log_warning "Element #{self.name} is missing the content definition for #{content_name}"
|
|
244
|
+
return nil
|
|
245
|
+
else
|
|
246
|
+
content_descriptions.detect { |d| d['name'] == content_name }
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Returns the definition for given content_name inside the available_contents
|
|
251
|
+
def available_content_description_for(content_name)
|
|
252
|
+
return nil if available_contents.blank?
|
|
253
|
+
available_contents.detect { |d| d['name'] == content_name }
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# returns the collection of available essence_types that can be created for this element depending on its description in elements.yml
|
|
257
|
+
def available_contents
|
|
258
|
+
definition['available_contents']
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Returns the contents ingredient for passed content name.
|
|
262
|
+
def ingredient(name)
|
|
263
|
+
content = content_by_name(name)
|
|
264
|
+
return nil if content.blank?
|
|
265
|
+
content.ingredient
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def has_ingredient?(name)
|
|
269
|
+
self.ingredient(name).present?
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Updates all related contents by calling +update_essence+ on each of them.
|
|
273
|
+
#
|
|
274
|
+
# @param contents_attributes [Hash]
|
|
275
|
+
# Hash of contents attributes.
|
|
276
|
+
# The keys has to be the #id of the content to update.
|
|
277
|
+
# The values a Hash of attribute names and values
|
|
278
|
+
#
|
|
279
|
+
# @return [Boolean]
|
|
280
|
+
# True if +self.errors+ are blank or +contents_attributes+ hash is nil
|
|
281
|
+
#
|
|
282
|
+
# == Example
|
|
283
|
+
#
|
|
284
|
+
# @element.update_contents({1 => {ingredient: 'Title'}, 2 => {link: 'https://google.com'}})
|
|
285
|
+
#
|
|
286
|
+
def update_contents(contents_attributes)
|
|
287
|
+
return true if contents_attributes.nil?
|
|
288
|
+
contents.each do |content|
|
|
289
|
+
content_hash = contents_attributes["#{content.id}"] || next
|
|
290
|
+
content.update_essence(content_hash) || errors.add(:base, :essence_validation_failed)
|
|
291
|
+
end
|
|
292
|
+
errors.blank?
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def essences
|
|
296
|
+
return [] if contents.blank?
|
|
297
|
+
contents.collect(&:essence)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Returns all essence_errors in the format:
|
|
301
|
+
#
|
|
302
|
+
# {
|
|
303
|
+
# essence.content.name => [error_message_for_validation_1, error_message_for_validation_2]
|
|
304
|
+
# }
|
|
305
|
+
#
|
|
306
|
+
# Get translated error messages with Element#essence_error_messages
|
|
307
|
+
#
|
|
308
|
+
def essence_errors
|
|
309
|
+
essence_errors = {}
|
|
310
|
+
essences.each do |essence|
|
|
311
|
+
unless essence.errors.blank?
|
|
312
|
+
essence_errors[essence.content.name] = essence.validation_errors
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
essence_errors
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Essence validation errors
|
|
319
|
+
#
|
|
320
|
+
# == Error messages are translated via I18n
|
|
321
|
+
#
|
|
322
|
+
# Inside your translation file add translations like:
|
|
323
|
+
#
|
|
324
|
+
# alchemy:
|
|
325
|
+
# content_validations:
|
|
326
|
+
# name_of_the_element:
|
|
327
|
+
# name_of_the_content:
|
|
328
|
+
# validation_error_type: Error Message
|
|
329
|
+
#
|
|
330
|
+
# NOTE: +validation_error_type+ has to be one of:
|
|
331
|
+
#
|
|
332
|
+
# * blank
|
|
333
|
+
# * taken
|
|
334
|
+
# * invalid
|
|
335
|
+
#
|
|
336
|
+
# === Example:
|
|
337
|
+
#
|
|
338
|
+
# de:
|
|
339
|
+
# alchemy:
|
|
340
|
+
# content_validations:
|
|
341
|
+
# contactform:
|
|
342
|
+
# email:
|
|
343
|
+
# invalid: 'Die Email hat nicht das richtige Format'
|
|
344
|
+
#
|
|
345
|
+
#
|
|
346
|
+
# == Error message translation fallbacks
|
|
347
|
+
#
|
|
348
|
+
# In order to not translate every single content for every element you can provide default error messages per content name:
|
|
349
|
+
#
|
|
350
|
+
# === Example
|
|
351
|
+
#
|
|
352
|
+
# en:
|
|
353
|
+
# alchemy:
|
|
354
|
+
# content_validations:
|
|
355
|
+
# fields:
|
|
356
|
+
# email:
|
|
357
|
+
# invalid: E-Mail has wrong format
|
|
358
|
+
# blank: E-Mail can't be blank
|
|
359
|
+
#
|
|
360
|
+
# And even further you can provide general field agnostic error messages:
|
|
361
|
+
#
|
|
362
|
+
# === Example
|
|
363
|
+
#
|
|
364
|
+
# en:
|
|
365
|
+
# alchemy:
|
|
366
|
+
# content_validations:
|
|
367
|
+
# errors:
|
|
368
|
+
# invalid: %{field} has wrong format
|
|
369
|
+
# blank: %{field} can't be blank
|
|
370
|
+
#
|
|
371
|
+
def essence_error_messages
|
|
372
|
+
messages = []
|
|
373
|
+
essence_errors.each do |content_name, errors|
|
|
374
|
+
errors.each do |error|
|
|
375
|
+
messages << I18n.t(
|
|
376
|
+
"#{self.name}.#{content_name}.#{error}",
|
|
377
|
+
scope: 'content_validations',
|
|
378
|
+
default: [
|
|
379
|
+
"fields.#{content_name}.#{error}".to_sym,
|
|
380
|
+
"errors.#{error}".to_sym
|
|
381
|
+
],
|
|
382
|
+
field: Content.translated_label_for(content_name, name)
|
|
383
|
+
)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
messages
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def contents_with_errors
|
|
390
|
+
contents.select(&:essence_validation_failed?)
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def has_validations?
|
|
394
|
+
!contents.detect(&:has_validations?).blank?
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def rtf_contents
|
|
398
|
+
contents.essence_richtexts
|
|
399
|
+
end
|
|
400
|
+
alias_method :richtext_contents, :rtf_contents
|
|
401
|
+
|
|
402
|
+
# Returns an array of all EssenceRichtext contents ids
|
|
403
|
+
#
|
|
404
|
+
def richtext_contents_ids
|
|
405
|
+
contents.essence_richtexts.pluck("#{Content.table_name}.id")
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# The names of all cells from given page this element could be placed in.
|
|
409
|
+
#
|
|
410
|
+
def available_page_cell_names(page)
|
|
411
|
+
cellnames = unique_available_page_cell_names(page)
|
|
412
|
+
if cellnames.blank? || !page.has_cells?
|
|
413
|
+
['for_other_elements']
|
|
414
|
+
else
|
|
415
|
+
cellnames
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Returns true if the definition of this element has a taggable true value.
|
|
420
|
+
def taggable?
|
|
421
|
+
definition['taggable'] == true
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# The element's view partial is dependent from its name
|
|
425
|
+
#
|
|
426
|
+
# == Define elements
|
|
427
|
+
#
|
|
428
|
+
# Elements are defined in the +config/alchemy/elements.yml+ file
|
|
429
|
+
#
|
|
430
|
+
# - name: article
|
|
431
|
+
# contents:
|
|
432
|
+
# ...
|
|
433
|
+
#
|
|
434
|
+
# == Override the view
|
|
435
|
+
#
|
|
436
|
+
# Element partials live in +app/views/alchemy/elements+
|
|
437
|
+
#
|
|
438
|
+
def to_partial_path
|
|
439
|
+
"alchemy/elements/#{name}_view"
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
# Returns the key that's taken for cache path.
|
|
443
|
+
#
|
|
444
|
+
# Uses the page's +published_at+ value that's updated when the user publishes the page.
|
|
445
|
+
#
|
|
446
|
+
# If the page is the current preview it uses the element's updated_at value as cache key.
|
|
447
|
+
#
|
|
448
|
+
def cache_key
|
|
449
|
+
if Page.current_preview == self.page
|
|
450
|
+
"alchemy/elements/#{id}-#{updated_at}"
|
|
451
|
+
else
|
|
452
|
+
"alchemy/elements/#{id}-#{page.published_at}"
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
private
|
|
457
|
+
|
|
458
|
+
def content_for_rss_meta(type)
|
|
459
|
+
description = content_descriptions.detect { |c| c["rss_#{type}"] }
|
|
460
|
+
return if description.blank?
|
|
461
|
+
contents.find_by(name: description['name'])
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
# creates the contents for this element as described in the elements.yml
|
|
465
|
+
def create_contents
|
|
466
|
+
contents = []
|
|
467
|
+
if definition["contents"].blank?
|
|
468
|
+
log_warning "Could not find any content descriptions for element: #{self.name}"
|
|
469
|
+
else
|
|
470
|
+
definition["contents"].each do |content_hash|
|
|
471
|
+
contents << Content.create_from_scratch(self, content_hash.symbolize_keys)
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
# Returns previous or next public element from same page.
|
|
477
|
+
#
|
|
478
|
+
# @param [String]
|
|
479
|
+
# Pass '>' or '<' to find next or previous public element.
|
|
480
|
+
# @param [String]
|
|
481
|
+
# Pass an element name to get previous of this kind.
|
|
482
|
+
#
|
|
483
|
+
def previous_or_next(dir, name = nil)
|
|
484
|
+
elements = page.elements.published.where("#{self.class.table_name}.position #{dir} #{position}")
|
|
485
|
+
elements = elements.named(name) if name.present?
|
|
486
|
+
elements.reorder("position #{dir == '>' ? 'ASC' : 'DESC'}").limit(1).first
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
# Returns all cells from given page this element could be placed in.
|
|
490
|
+
#
|
|
491
|
+
def available_page_cells(page)
|
|
492
|
+
page.cells.select do |cell|
|
|
493
|
+
cell.available_elements.include?(self.name)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# Returns all uniq cell names from given page this element could be placed in.
|
|
498
|
+
#
|
|
499
|
+
def unique_available_page_cell_names(page)
|
|
500
|
+
available_page_cells(page).collect(&:name).uniq
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
# If element has a +cell+ associated,
|
|
504
|
+
# it updates it's timestamp.
|
|
505
|
+
#
|
|
506
|
+
# Called after_update
|
|
507
|
+
#
|
|
508
|
+
def touch_cell
|
|
509
|
+
self.cell.touch
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
end
|
|
513
|
+
end
|