dm_cms 4.2.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +22 -0
- data/README.md +31 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/dm_cms/admin.js +58 -0
- data/app/assets/javascripts/dm_cms/application.js +16 -0
- data/app/assets/stylesheets/dm_cms/admin.css +3 -0
- data/app/assets/stylesheets/dm_cms/application.css +13 -0
- data/app/controllers/dm_cms/admin/admin_controller.rb +14 -0
- data/app/controllers/dm_cms/admin/cms_blogs_controller.rb +89 -0
- data/app/controllers/dm_cms/admin/cms_contentitems_controller.rb +96 -0
- data/app/controllers/dm_cms/admin/cms_pages_controller.rb +100 -0
- data/app/controllers/dm_cms/admin/cms_posts_controller.rb +67 -0
- data/app/controllers/dm_cms/admin/cms_snippets_controller.rb +73 -0
- data/app/controllers/dm_cms/admin/dashboard_controller.rb +12 -0
- data/app/controllers/dm_cms/admin/media_files_controller.rb +80 -0
- data/app/controllers/dm_cms/application_controller.rb +9 -0
- data/app/controllers/dm_cms/blogs_controller.rb +50 -0
- data/app/controllers/dm_cms/comments_controller.rb +3 -0
- data/app/controllers/dm_cms/contact_form_controller.rb +27 -0
- data/app/controllers/dm_cms/pages_controller.rb +67 -0
- data/app/controllers/dm_cms/posts_controller.rb +69 -0
- data/app/datatables/blog_user_datatable.rb +79 -0
- data/app/helpers/dm_cms/analytics_helper.rb +27 -0
- data/app/helpers/dm_cms/application_helper.rb +4 -0
- data/app/helpers/dm_cms/cms_contentitems_helper.rb +8 -0
- data/app/helpers/dm_cms/cms_pages_helper.rb +30 -0
- data/app/helpers/dm_cms/pages_helper.rb +204 -0
- data/app/helpers/dm_cms/posts_helper.rb +26 -0
- data/app/helpers/dm_cms/render_helper.rb +50 -0
- data/app/inputs/media_input.rb +17 -0
- data/app/liquid/tags/markdown.rb +30 -0
- data/app/mailers/post_notify_mailer.rb +36 -0
- data/app/models/cms_blog.rb +89 -0
- data/app/models/cms_contentitem.rb +76 -0
- data/app/models/cms_page.rb +227 -0
- data/app/models/cms_post.rb +76 -0
- data/app/models/cms_snippet.rb +42 -0
- data/app/models/contact_form.rb +28 -0
- data/app/models/dm_cms/concerns/ability.rb +54 -0
- data/app/models/dm_cms/permitted_params.rb +34 -0
- data/app/models/media_file.rb +102 -0
- data/app/presenters/cms_blog_presenter.rb +15 -0
- data/app/presenters/cms_page_presenter.rb +23 -0
- data/app/presenters/cms_post_presenter.rb +11 -0
- data/app/presenters/cms_snippet_presenter.rb +10 -0
- data/app/uploaders/media_uploader.rb +169 -0
- data/app/views/customized/analytics/_google_analytics.html.erb +11 -0
- data/app/views/dm_cms/admin/cms_blogs/_form.html.erb +34 -0
- data/app/views/dm_cms/admin/cms_blogs/edit.html.erb +2 -0
- data/app/views/dm_cms/admin/cms_blogs/index.html.erb +44 -0
- data/app/views/dm_cms/admin/cms_blogs/new.html.erb +2 -0
- data/app/views/dm_cms/admin/cms_blogs/show.html.erb +167 -0
- data/app/views/dm_cms/admin/cms_contentitems/_form.html.erb +43 -0
- data/app/views/dm_cms/admin/cms_contentitems/_form_dialog.html.erb +17 -0
- data/app/views/dm_cms/admin/cms_contentitems/edit.html.erb +1 -0
- data/app/views/dm_cms/admin/cms_contentitems/markdown.html.erb +21 -0
- data/app/views/dm_cms/admin/cms_contentitems/new_content.html.erb +1 -0
- data/app/views/dm_cms/admin/cms_pages/_content_toolbar.html.erb +11 -0
- data/app/views/dm_cms/admin/cms_pages/_form.html.erb +50 -0
- data/app/views/dm_cms/admin/cms_pages/_tree.html.erb +20 -0
- data/app/views/dm_cms/admin/cms_pages/_tree_sidebar.html.erb +8 -0
- data/app/views/dm_cms/admin/cms_pages/edit.html.erb +2 -0
- data/app/views/dm_cms/admin/cms_pages/index.html.erb +32 -0
- data/app/views/dm_cms/admin/cms_pages/new_page.html.erb +2 -0
- data/app/views/dm_cms/admin/cms_pages/show.html.erb +54 -0
- data/app/views/dm_cms/admin/cms_posts/_form.html.erb +59 -0
- data/app/views/dm_cms/admin/cms_posts/edit.html.erb +2 -0
- data/app/views/dm_cms/admin/cms_posts/new.html.erb +1 -0
- data/app/views/dm_cms/admin/cms_snippets/_form.html.erb +28 -0
- data/app/views/dm_cms/admin/cms_snippets/edit.html.erb +1 -0
- data/app/views/dm_cms/admin/cms_snippets/index.html.erb +29 -0
- data/app/views/dm_cms/admin/cms_snippets/new.html.erb +1 -0
- data/app/views/dm_cms/admin/dashboard/_widget_blog_comments.html.erb +37 -0
- data/app/views/dm_cms/admin/dashboard/widget_blog_comments.js.erb +1 -0
- data/app/views/dm_cms/admin/media_files/_form.html.erb +102 -0
- data/app/views/dm_cms/admin/media_files/edit.html.erb +3 -0
- data/app/views/dm_cms/admin/media_files/index.html.erb +98 -0
- data/app/views/dm_cms/admin/media_files/new.html.erb +3 -0
- data/app/views/dm_cms/admin/shared/_liquid_tags_ref.html.erb +35 -0
- data/app/views/dm_cms/blogs/show.html.erb +0 -0
- data/app/views/dm_cms/blogs/toggle_follow.js.coffee +5 -0
- data/app/views/dm_cms/contact_form/create.html.erb +2 -0
- data/app/views/dm_cms/contact_form/create.js.erb +2 -0
- data/app/views/dm_cms/pages/_content_fragment.html.erb +13 -0
- data/app/views/dm_cms/pages/_snippet_fragment.html.erb +12 -0
- data/app/views/dm_cms/pages/coming_soon.html.erb +2 -0
- data/app/views/dm_cms/pages/show.html.erb +0 -0
- data/app/views/dm_cms/posts/show.html.erb +0 -0
- data/app/views/dm_cms/shared/_comment.html.erb +22 -0
- data/app/views/dm_cms/shared/_comment_form.html.erb +16 -0
- data/app/views/dm_cms/shared/_comment_list.html.erb +11 -0
- data/app/views/dm_cms/shared/_social_buttons.html.erb +6 -0
- data/app/views/layouts/email_templates/dm_cms_email_layout.html.erb +320 -0
- data/app/views/layouts/email_templates/dm_cms_email_layout.text.erb +1 -0
- data/app/views/layouts/email_templates/dm_cms_post_notify.html.erb +13 -0
- data/app/views/layouts/email_templates/dm_cms_post_notify.text.erb +9 -0
- data/app/views/liquid_tags/_contact_form.html.erb +17 -0
- data/config/initializers/liquid_init.rb +2 -0
- data/config/locales/cms.cs.yml +42 -0
- data/config/locales/cms.de.yml +42 -0
- data/config/locales/cms.en.yml +42 -0
- data/config/locales/cms.fi.yml +42 -0
- data/config/locales/cms.ja.yml +42 -0
- data/config/routes.rb +70 -0
- data/db/migrate/20121103181909_create_cms.rb +91 -0
- data/db/migrate/20130206213720_add_account_to_cms.rb +10 -0
- data/db/migrate/20130507123255_create_blog.rb +61 -0
- data/db/migrate/20130531212537_add_notification_sent.rb +5 -0
- data/db/migrate/20130605184116_add_blog_comment.rb +7 -0
- data/db/migrate/20131128201053_add_blog_image.rb +5 -0
- data/db/migrate/20140217135228_rename_snippet_slug.rb +13 -0
- data/db/migrate/20140303121217_add_requires_subscription_blog.rb +7 -0
- data/db/migrate/20140328205246_add_pages_ranked_model.rb +22 -0
- data/db/migrate/20140423113417_add_blog_owner.rb +6 -0
- data/db/migrate/20140428122156_create_media_files.rb +29 -0
- data/db/migrate/20140523134543_add_cmspage_summary.rb +6 -0
- data/db/migrate/20140601151631_add_blog_image_email_header.rb +5 -0
- data/db/migrate/20141004154725_add_header_image.rb +9 -0
- data/db/migrate/20160821150108_index_foreign_keys_in_cms_blogs.rb +6 -0
- data/db/migrate/20160821150109_index_foreign_keys_in_cms_media_files.rb +6 -0
- data/db/migrate/20160821150110_index_foreign_keys_in_cms_posts.rb +6 -0
- data/lib/dm_cms.rb +4 -0
- data/lib/dm_cms/engine.rb +16 -0
- data/lib/dm_cms/liquid/filters/liquid_filters.rb +11 -0
- data/lib/dm_cms/liquid/tags/contact_form.rb +35 -0
- data/lib/dm_cms/liquid/tags/div.rb +42 -0
- data/lib/dm_cms/liquid/tags/image.rb +76 -0
- data/lib/dm_cms/liquid/tags/quote.rb +38 -0
- data/lib/dm_cms/liquid/tags/snippet.rb +37 -0
- data/lib/dm_cms/liquid/tags/url_asset.rb +41 -0
- data/lib/dm_cms/liquid/tags/url_media.rb +42 -0
- data/lib/dm_cms/liquid/tags/url_protected.rb +31 -0
- data/lib/tasks/dm_cms_tasks.rake +4 -0
- data/spec/controllers/admin/cms_blogs_controller_spec.rb +173 -0
- data/spec/controllers/admin/cms_pages_controller_spec.rb +182 -0
- data/spec/controllers/admin/cms_posts_controller_spec.rb +166 -0
- data/spec/dummy/README.rdoc +28 -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/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/ability.rb +12 -0
- data/spec/dummy/app/models/user.rb +6 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -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/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +82 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/_themes_for_rails.rb +39 -0
- data/spec/dummy/config/initializers/account_initialization.rb +28 -0
- data/spec/dummy/config/initializers/assets.rb +8 -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/dm_core.rb +6 -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/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +19 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20141114170927_add_globalize_countries.dm_core.rb +50 -0
- data/spec/dummy/db/migrate/20141114170928_devise_create_users.dm_core.rb +46 -0
- data/spec/dummy/db/migrate/20141114170929_add_user_fields.dm_core.rb +14 -0
- data/spec/dummy/db/migrate/20141114170930_rolify_create_roles.dm_core.rb +20 -0
- data/spec/dummy/db/migrate/20141114170931_add_last_access.dm_core.rb +10 -0
- data/spec/dummy/db/migrate/20141114170932_create_versions.dm_core.rb +19 -0
- data/spec/dummy/db/migrate/20141114170933_add_object_changes_column_to_versions.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170934_create_dm_core_accounts.dm_core.rb +13 -0
- data/spec/dummy/db/migrate/20141114170935_add_account_to_users.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170936_create_preferences.dm_core.rb +13 -0
- data/spec/dummy/db/migrate/20141114170937_create_comments.dm_core.rb +22 -0
- data/spec/dummy/db/migrate/20141114170938_add_activity.dm_core.rb +21 -0
- data/spec/dummy/db/migrate/20141114170939_add_type_to_comments.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170940_add_category.dm_core.rb +28 -0
- data/spec/dummy/db/migrate/20141114170941_create_email_table.dm_core.rb +26 -0
- data/spec/dummy/db/migrate/20141114170942_add_user_profile.dm_core.rb +46 -0
- data/spec/dummy/db/migrate/20141114170943_add_profile_email.dm_core.rb +14 -0
- data/spec/dummy/db/migrate/20141114170944_create_payment_history.dm_core.rb +37 -0
- data/spec/dummy/db/migrate/20141114170945_change_anchor_field.dm_core.rb +10 -0
- data/spec/dummy/db/migrate/20141114170946_create_user_site_profile.dm_core.rb +27 -0
- data/spec/dummy/db/migrate/20141114170947_add_avatar.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170948_add_notify_to_payment_history.dm_core.rb +8 -0
- data/spec/dummy/db/migrate/20141114170949_acts_as_votable_migration.dm_core.rb +28 -0
- data/spec/dummy/db/migrate/20141114170950_add_user_site_profile_uuid.dm_core.rb +19 -0
- data/spec/dummy/db/migrate/20141114170951_add_invoice_id.dm_core.rb +7 -0
- data/spec/dummy/db/migrate/20141114170952_acts_as_follower_migration.dm_core.rb +18 -0
- data/spec/dummy/db/migrate/20141114170953_rename_invoice_id.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170954_add_core_addresses.dm_core.rb +18 -0
- data/spec/dummy/db/migrate/20141114170955_papertrail_increase_column.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170956_acts_as_taggable_on_migration.dm_core.rb +32 -0
- data/spec/dummy/db/migrate/20141114170957_add_missing_unique_indices.dm_core.rb +23 -0
- data/spec/dummy/db/migrate/20141114170958_add_taggings_counter_cache_to_tags.dm_core.rb +16 -0
- data/spec/dummy/db/migrate/20141114170959_create_custom_fields.dm_core.rb +40 -0
- data/spec/dummy/db/migrate/20141114170960_add_missing_taggable_index.dm_core.rb +11 -0
- data/spec/dummy/db/migrate/20141114170961_create_documents.dm_knowledge.rb +19 -0
- data/spec/dummy/db/migrate/20141114170962_add_document_notes.dm_knowledge.rb +7 -0
- data/spec/dummy/db/migrate/20160128134522_add_favored_locale.dm_core.rb +17 -0
- data/spec/dummy/db/migrate/20160128134523_update_papertrail_v4.dm_core.rb +41 -0
- data/spec/dummy/db/schema.rb +590 -0
- data/spec/dummy/db/seeds.rb +18 -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/dummy/themes/_mbus/_readme.md +6 -0
- data/spec/dummy/themes/_mbus/_theme.yml +21 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/application.js +9 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/bootstrap.js +2114 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/bootstrap.min.js +6 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/contact_me.js +75 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/jqBootstrapValidation.js +912 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/jquery-1.11.0.js +4 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/application.css +14 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/bootstrap.css +6203 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/bootstrap.min.css +5 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/css/font-awesome.css +1566 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/css/font-awesome.min.css +4 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/FontAwesome.otf +0 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.eot +0 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.svg +504 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.ttf +0 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.woff +0 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/bordered-pulled.less +16 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/core.less +12 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/fixed-width.less +6 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/font-awesome.less +17 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/icons.less +506 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/larger.less +13 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/list.less +19 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/mixins.less +20 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/path.less +14 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/rotated-flipped.less +9 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/spinning.less +32 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/stacked.less +20 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/variables.less +515 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_bordered-pulled.scss +16 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_core.scss +12 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_fixed-width.scss +6 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_icons.scss +506 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_larger.scss +13 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_list.scss +19 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_mixins.scss +20 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_path.scss +14 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_rotated-flipped.scss +9 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_spinning.scss +32 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_stacked.scss +20 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_variables.scss +515 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/font-awesome.scss +17 -0
- data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/modern-business.css +93 -0
- data/spec/dummy/themes/_mbus/theme_support/config/load_theme.rb +0 -0
- data/spec/dummy/themes/_mbus/theme_support/locales/site.cs.yml +57 -0
- data/spec/dummy/themes/_mbus/theme_support/locales/site.de.yml +57 -0
- data/spec/dummy/themes/_mbus/theme_support/locales/site.en.yml +57 -0
- data/spec/dummy/themes/_mbus/theme_support/locales/site.fi.yml +58 -0
- data/spec/dummy/themes/_mbus/theme_support/locales/site.ja.yml +57 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_blog_right_sidebar.html.erb +91 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment.html.erb +21 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_form.html.erb +16 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_list.html.erb +7 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_section.html.erb +17 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_footer.html.erb +11 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_header.html.erb +39 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_top.html.erb +24 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_post_summary_item.html.erb +11 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_social_buttons_initialization.html.erb +10 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/blog.html.erb +47 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/blog_post.html.erb +55 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/content_full_width.html.erb +28 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/content_with_left_nav.html.erb +44 -0
- data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/index.html.erb +19 -0
- data/spec/dummy/themes/local/_theme.yml +8 -0
- data/spec/factories/accounts.rb +17 -0
- data/spec/factories/blogs.rb +19 -0
- data/spec/factories/posts.rb +23 -0
- data/spec/factories/user_profiles.rb +10 -0
- data/spec/factories/users.rb +19 -0
- data/spec/features/admin/blog_admin_spec.rb +16 -0
- data/spec/models/cms_blog_spec.rb +37 -0
- data/spec/models/cms_page_spec.rb +9 -0
- data/spec/models/cms_post_spec.rb +44 -0
- data/spec/rails_helper.rb +70 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/support/accounts.rb +17 -0
- data/spec/support/devise.rb +44 -0
- data/spec/support/fix_locale.rb +57 -0
- metadata +545 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module Liquid
|
2
|
+
class Markdown < DmCore::LiquidBlock
|
3
|
+
include DmCore::LiquidHelper
|
4
|
+
|
5
|
+
#------------------------------------------------------------------------------
|
6
|
+
def render(context)
|
7
|
+
markdown(super, safe: false)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.details
|
11
|
+
{ name: self.tag_name,
|
12
|
+
summary: 'Process text with Markdown',
|
13
|
+
category: 'structure',
|
14
|
+
description: <<-END_OF_DESCRIPTION
|
15
|
+
Process the enclosed text with Markdown. Useful when your processing a page as HTML, but you would like to use
|
16
|
+
Markdown in certain sections.
|
17
|
+
|
18
|
+
~~~
|
19
|
+
{% markdown %}
|
20
|
+
...content
|
21
|
+
{% endmarkdown %}
|
22
|
+
~~~
|
23
|
+
END_OF_DESCRIPTION
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Template.register_tag('markdown', Markdown)
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class PostNotifyMailer < DmCore::SiteMailer
|
2
|
+
|
3
|
+
helper DmCms::PostsHelper
|
4
|
+
helper DmCore::LiquidHelper
|
5
|
+
helper DmCore::UrlHelper
|
6
|
+
helper DmCore::AccountHelper
|
7
|
+
|
8
|
+
layout 'email_templates/dm_cms_email_layout'
|
9
|
+
|
10
|
+
# send notification email, using the users preferred locale if possible
|
11
|
+
#------------------------------------------------------------------------------
|
12
|
+
def post_notify(user, post, account)
|
13
|
+
Account.current = account # needed so this can run in a background job
|
14
|
+
# Account.current.set_default_values
|
15
|
+
locale = account.verify_locale(user.locale)
|
16
|
+
I18n.with_locale(locale) do
|
17
|
+
@subject = "Blog: #{post.cms_blog.title} :: #{post.title}"
|
18
|
+
@recipients = user.email
|
19
|
+
@blog_title = post.cms_blog.title
|
20
|
+
@post_title = post.title
|
21
|
+
@post_link = dm_cms.post_show_url(post.cms_blog.slug, post.slug, locale: locale, host: account.url_host, protocol: account.url_protocol)
|
22
|
+
@post = post
|
23
|
+
@header_image = post.cms_blog.image_email_header || post.cms_blog.header_image
|
24
|
+
|
25
|
+
headers = { "Return-Path" => account.preferred_blog_from_email || account.preferred_smtp_from_email }
|
26
|
+
mail( from: account.preferred_blog_from_email || account.preferred_smtp_from_email,
|
27
|
+
reply_to: account.preferred_blog_from_email || account.preferred_smtp_from_email,
|
28
|
+
to: @recipients, subject: @subject,
|
29
|
+
theme: account.account_prefix) do |format|
|
30
|
+
format.text { render "layouts/email_templates/dm_cms_post_notify.text.erb" }
|
31
|
+
format.html { render "layouts/email_templates/dm_cms_post_notify.html.erb" }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class CmsBlog < ActiveRecord::Base
|
2
|
+
include DmCore::Concerns::PublicPrivate
|
3
|
+
|
4
|
+
# --- globalize
|
5
|
+
translates :title, :fallbacks_for_empty_translations => true
|
6
|
+
globalize_accessors :locales => DmCore::Language.language_array
|
7
|
+
|
8
|
+
# --- FriendlyId
|
9
|
+
extend FriendlyId
|
10
|
+
include DmCore::Concerns::FriendlyId
|
11
|
+
|
12
|
+
acts_as_followable
|
13
|
+
|
14
|
+
resourcify
|
15
|
+
|
16
|
+
include RankedModel
|
17
|
+
ranks :row_order, :with_same => :account_id
|
18
|
+
|
19
|
+
default_scope { where(account_id: Account.current.id).order(:row_order) }
|
20
|
+
scope :published, -> { where(:published => true) }
|
21
|
+
|
22
|
+
has_many :posts, -> { order('published_on DESC') }, :class_name => 'CmsPost', :dependent => :destroy
|
23
|
+
belongs_to :account
|
24
|
+
belongs_to :owner, :polymorphic => true
|
25
|
+
|
26
|
+
preference :show_social_buttons, :boolean, :default => false
|
27
|
+
preference :header_accent_color, :string
|
28
|
+
|
29
|
+
validates :title, presence_default_locale: true
|
30
|
+
validates_uniqueness_of :slug, scope: :account_id
|
31
|
+
|
32
|
+
#------------------------------------------------------------------------------
|
33
|
+
def model_slug
|
34
|
+
send("title_#{Account.current.preferred_default_locale}")
|
35
|
+
end
|
36
|
+
|
37
|
+
#------------------------------------------------------------------------------
|
38
|
+
def is_published?
|
39
|
+
published
|
40
|
+
end
|
41
|
+
|
42
|
+
#------------------------------------------------------------------------------
|
43
|
+
def show_social_buttons?
|
44
|
+
preferred_show_social_buttons? && !is_private?
|
45
|
+
end
|
46
|
+
|
47
|
+
# Are any of the blogs readable by this user? One positive is all need...
|
48
|
+
#------------------------------------------------------------------------------
|
49
|
+
def any_readable_blogs?(user)
|
50
|
+
CmsBlog.all.any? { |b| b.can_be_read_by?(user) }
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the header image, or a default if not specified
|
54
|
+
#------------------------------------------------------------------------------
|
55
|
+
def header_image(default = nil)
|
56
|
+
self.attributes['header_image'] || default
|
57
|
+
end
|
58
|
+
|
59
|
+
#------------------------------------------------------------------------------
|
60
|
+
def header_accent_color(default = '')
|
61
|
+
self.preferred_header_accent_color || default
|
62
|
+
end
|
63
|
+
|
64
|
+
# Grab a list of the recent posts. Can pull from all blogs or a specific
|
65
|
+
# one.
|
66
|
+
#------------------------------------------------------------------------------
|
67
|
+
def self.recent_posts(options = {user: nil, limit: 5, blog: nil})
|
68
|
+
if options[:blog].nil? # get all available to user
|
69
|
+
query_blogs = CmsBlog.available_to_user(options[:user]).map(&:id)
|
70
|
+
else
|
71
|
+
query_blogs = CmsBlog.friendly.find(options[:blog])
|
72
|
+
end
|
73
|
+
CmsPost.where(cms_blog_id: query_blogs).includes(:cms_blog, :translations).published.order('published_on DESC').limit(options[:limit])
|
74
|
+
end
|
75
|
+
|
76
|
+
# Send new post notifications to any followers
|
77
|
+
# NOTE: Currently, we don't do automated notifications for new blog posts.
|
78
|
+
# You must click on the button in the backend to trigger it. At the moment,
|
79
|
+
# we desire that extra level of control. If we decided to enable this in the
|
80
|
+
# future, selecting using the notification_sent_on column, make sure that
|
81
|
+
# all current posts are non-nil, so we don't trigger a much of old posts
|
82
|
+
# being sent
|
83
|
+
#------------------------------------------------------------------------------
|
84
|
+
# def self.notify_followers(start_time, end_time = Time.now)
|
85
|
+
# posts = CmsPost.published.includes(:cms_blog).where(cms_blogs: {published: true}).where(notification_sent_on: nil)
|
86
|
+
# posts.each {|post| post.send_notification_emails }
|
87
|
+
# end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Note: fragment caching is used during rendering. The cache key is based
|
2
|
+
# on both the model and the current locale (because each model supports
|
3
|
+
# multiple translations). The cache will be busted automatically since
|
4
|
+
# the updated_at attribute will be updated on save.
|
5
|
+
#------------------------------------------------------------------------------
|
6
|
+
class CmsContentitem < ActiveRecord::Base
|
7
|
+
class Translation < ::Globalize::ActiveRecord::Translation
|
8
|
+
has_paper_trail
|
9
|
+
end
|
10
|
+
|
11
|
+
belongs_to :cms_page
|
12
|
+
|
13
|
+
include RankedModel
|
14
|
+
ranks :row_order, with_same: [:account_id, :cms_page_id]
|
15
|
+
default_scope { where(account_id: Account.current.id) }
|
16
|
+
|
17
|
+
# --- globalize (don't use versioning: true, translations erased when updating regular model data. Maybe fixed in github version)
|
18
|
+
translates :content, fallbacks_for_empty_translations: true
|
19
|
+
globalize_accessors locales: DmCore::Language.language_array
|
20
|
+
|
21
|
+
# --- versioning - skip anything translated
|
22
|
+
has_paper_trail skip: :content
|
23
|
+
|
24
|
+
amoeba do
|
25
|
+
enable
|
26
|
+
end
|
27
|
+
# --- validations
|
28
|
+
validates_presence_of :itemtype, :container
|
29
|
+
validates_length_of :itemtype, maximum: 30
|
30
|
+
validates_length_of :container, maximum: 30
|
31
|
+
validate :validate_conflict, on: :update
|
32
|
+
validates :content, liquid: { locales: true }, presence_default_locale: true
|
33
|
+
|
34
|
+
# --- content types supported
|
35
|
+
CONTENT_TYPES = [ 'Markdown', 'Textile', 'HTML' ]
|
36
|
+
|
37
|
+
#------------------------------------------------------------------------------
|
38
|
+
def original_updated_on
|
39
|
+
@original_updated_on || self.updated_on.to_f
|
40
|
+
end
|
41
|
+
attr_writer :original_updated_on
|
42
|
+
|
43
|
+
# Try to see if the record has been changed by someone while being edited by someone
|
44
|
+
# else. If original_updated_on is not set, then don't check - allows acts_as_list
|
45
|
+
# methods to update without causing a problem.
|
46
|
+
# [todo] still needed since we don't use acts_as_list anymore?
|
47
|
+
#------------------------------------------------------------------------------
|
48
|
+
def validate_conflict
|
49
|
+
if @conflict || (!@original_updated_on.nil? && self.updated_on.to_f > @original_updated_on.to_f)
|
50
|
+
@conflict = true
|
51
|
+
@original_updated_on = nil
|
52
|
+
errors.add :base, "This record was changed while you were editing."
|
53
|
+
changes.each do |attribute, values|
|
54
|
+
errors.add attribute, "was #{values.first}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generate any data to pass when rendering with Liquid
|
60
|
+
#------------------------------------------------------------------------------
|
61
|
+
def to_liquid
|
62
|
+
cms_page.to_liquid
|
63
|
+
end
|
64
|
+
|
65
|
+
#------------------------------------------------------------------------------
|
66
|
+
def deep_clone(new_cms_page_id)
|
67
|
+
new_cms_contentitem = self.clone
|
68
|
+
new_cms_contentitem.cms_page_id = new_cms_page_id
|
69
|
+
|
70
|
+
DmCore::Language.language_array.each do |locale|
|
71
|
+
eval("new_cms_contentitem.content_#{locale[:lang]} = content_#{locale[:lang]} unless content_#{locale[:lang]}.nil?")
|
72
|
+
end
|
73
|
+
new_cms_contentitem.save
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# Implementation Note: if the 'menutitle' is blank, that indicates the page should
|
2
|
+
# not be shown in menus. It can still be published and directly linked to, but
|
3
|
+
# it should not show up in any auto-generated menus. This gives the ability
|
4
|
+
# to have many pages in a section, with some of them 'hidden' from the main menu
|
5
|
+
# lists, but can still be linked to and shown.
|
6
|
+
#------------------------------------------------------------------------------
|
7
|
+
class CmsPage < ActiveRecord::Base
|
8
|
+
class Translation < ::Globalize::ActiveRecord::Translation
|
9
|
+
has_paper_trail
|
10
|
+
end
|
11
|
+
|
12
|
+
#--- NOTE: if you add any new fields, then update the duplicate_with_associations method
|
13
|
+
|
14
|
+
# --- globalize (don't use versioning: true, translations erased when updating regular model data. Maybe fixed in github version)
|
15
|
+
translates :title, :summary, :menutitle, :fallbacks_for_empty_translations => true #, :versioning => true
|
16
|
+
globalize_accessors :locales => DmCore::Language.language_array
|
17
|
+
|
18
|
+
# --- versioning - skip anything translated
|
19
|
+
has_paper_trail :skip => [:title, :menutitle]
|
20
|
+
|
21
|
+
# --- FriendlyId
|
22
|
+
extend FriendlyId
|
23
|
+
include DmCore::Concerns::FriendlyId
|
24
|
+
|
25
|
+
# --- associations
|
26
|
+
has_many :cms_contentitems, -> { order(:row_order) }, :dependent => :destroy
|
27
|
+
has_ancestry :cache_depth => true
|
28
|
+
before_save :cache_depth # fixes bug where depth not recalculated when subtree moved
|
29
|
+
|
30
|
+
include RankedModel
|
31
|
+
ranks :row_order, :with_same => [:account_id, :ancestry]
|
32
|
+
|
33
|
+
default_scope { where(account_id: Account.current.id).order("ancestry, row_order ASC") }
|
34
|
+
|
35
|
+
preference :show_social_buttons, :boolean, :default => false
|
36
|
+
preference :header_accent_color, :string
|
37
|
+
|
38
|
+
amoeba do
|
39
|
+
enable
|
40
|
+
end
|
41
|
+
|
42
|
+
# --- validations
|
43
|
+
validates_length_of :slug, :maximum => 50
|
44
|
+
validates_presence_of :slug
|
45
|
+
validates_uniqueness_of :slug, :scope => :account_id
|
46
|
+
validates_length_of :pagetype, :maximum => 20
|
47
|
+
validates_presence_of :pagetype
|
48
|
+
validates_length_of :template, :maximum => 50
|
49
|
+
|
50
|
+
# --- list of pagetypes
|
51
|
+
PAGETYPE = ['content', 'pagelink', 'controller/action', 'link', 'divider']
|
52
|
+
|
53
|
+
# Base the slug on the default locale
|
54
|
+
#------------------------------------------------------------------------------
|
55
|
+
def model_slug
|
56
|
+
send("title_#{Account.current.preferred_default_locale}")
|
57
|
+
end
|
58
|
+
|
59
|
+
# is the page published, based on the publish flag and the publish dates
|
60
|
+
#------------------------------------------------------------------------------
|
61
|
+
def is_published?
|
62
|
+
# --- {todo} need to hook in the publish dates
|
63
|
+
published
|
64
|
+
end
|
65
|
+
|
66
|
+
#------------------------------------------------------------------------------
|
67
|
+
def show_social_buttons?
|
68
|
+
preferred_show_social_buttons?
|
69
|
+
end
|
70
|
+
|
71
|
+
# is this a special divider page - which doesn't get rendered, it's for adding
|
72
|
+
# categories in a sub menu
|
73
|
+
#------------------------------------------------------------------------------
|
74
|
+
def divider?
|
75
|
+
pagetype == 'divider'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return the template name. If it's empty, the go to each parent until one
|
79
|
+
# is found.
|
80
|
+
# raise an exception if there is no page template - otherwise error is hidden
|
81
|
+
#------------------------------------------------------------------------------
|
82
|
+
def page_template
|
83
|
+
page = self
|
84
|
+
page = page.parent while page.template.blank? && !page.is_root?
|
85
|
+
raise "No template available for page #{self.slug}" if page.template.blank?
|
86
|
+
return page.template
|
87
|
+
end
|
88
|
+
|
89
|
+
# Return a list of published children pages
|
90
|
+
# => user, to check for permissions
|
91
|
+
# => include_blank_titles to true to include pages with blank titles.
|
92
|
+
# do not include by default
|
93
|
+
#------------------------------------------------------------------------------
|
94
|
+
def published_children(user, options = {include_blank_titles: false})
|
95
|
+
pages = []
|
96
|
+
if self.has_children?
|
97
|
+
self.children.each do |child|
|
98
|
+
if child.is_published? || (user && user.is_admin?)
|
99
|
+
pages << child unless child[:menutitle].blank? && !options[:include_blank_titles]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
return pages
|
104
|
+
end
|
105
|
+
|
106
|
+
# Return the header image, or a default if not specified
|
107
|
+
#------------------------------------------------------------------------------
|
108
|
+
def header_image(default = nil)
|
109
|
+
self.attributes['header_image'] || default
|
110
|
+
end
|
111
|
+
|
112
|
+
#------------------------------------------------------------------------------
|
113
|
+
def header_accent_color(default = '')
|
114
|
+
self.preferred_header_accent_color || default
|
115
|
+
end
|
116
|
+
|
117
|
+
#------------------------------------------------------------------------------
|
118
|
+
def self.page_types
|
119
|
+
PAGETYPE
|
120
|
+
end
|
121
|
+
|
122
|
+
# Generate any data to pass when rendering with Liquid
|
123
|
+
#------------------------------------------------------------------------------
|
124
|
+
def to_liquid
|
125
|
+
{ 'page' =>
|
126
|
+
{
|
127
|
+
'title' => self.title,
|
128
|
+
'menutitle' => self.menutitle,
|
129
|
+
'slug' => self.slug
|
130
|
+
},
|
131
|
+
'subscription' =>
|
132
|
+
{
|
133
|
+
'trial?' => false,
|
134
|
+
'active?' => true
|
135
|
+
}
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
# Check if this page has been cookied. If needed, we will set a cookie, using
|
140
|
+
# the page's slug, to a value of 1. This indicates that the page has
|
141
|
+
# been visited. This is only needed in cases where we want to ensure a page
|
142
|
+
# has been visited before enabling some other function.
|
143
|
+
#
|
144
|
+
# If cookie_hash is empty, then we don't care if the page has been visited or not,
|
145
|
+
# simply return true
|
146
|
+
#------------------------------------------------------------------------------
|
147
|
+
def visited?(cookie_hash)
|
148
|
+
return ((cookie_hash.empty? || cookie_hash[slug] == "1") ? true : false)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Create a default site. Check if pages exists first, so we can add missing
|
152
|
+
# pages to already created sites.
|
153
|
+
#------------------------------------------------------------------------------
|
154
|
+
def self.create_default_site
|
155
|
+
#--- index page
|
156
|
+
unless (site = CmsPage.find_by_slug('index'))
|
157
|
+
site = CmsPage.create(:slug => 'index', :pagetype => 'content', :template => 'index',
|
158
|
+
:published => true, :title => 'Front Page')
|
159
|
+
end
|
160
|
+
|
161
|
+
unless (standard = CmsPage.find_by_slug('standard_pages'))
|
162
|
+
standard = site.children.create(slug: 'standard_pages', pagetype: 'pagelink',
|
163
|
+
published: false, title: 'Standard Pages')
|
164
|
+
end
|
165
|
+
|
166
|
+
unless CmsPage.find_by_slug('missing')
|
167
|
+
standard.children.create( :slug => 'missing', :pagetype => 'content', :template => '404',
|
168
|
+
:published => true, :title => 'Page Missing')
|
169
|
+
end
|
170
|
+
|
171
|
+
unless CmsPage.find_by_slug('coming_soon')
|
172
|
+
standard.children.create( :slug => 'coming_soon', :pagetype => 'content', :template => 'coming_soon',
|
173
|
+
:published => true, :title => 'Coming Soon')
|
174
|
+
end
|
175
|
+
unless CmsPage.find_by_slug('signup_success')
|
176
|
+
standard.children.create( :slug => 'signup_success', :pagetype => 'pagelink',
|
177
|
+
:link => 'index', :published => true, :title => 'Signup Success')
|
178
|
+
end
|
179
|
+
unless CmsPage.find_by_slug('confirmation_success')
|
180
|
+
standard.children.create( :slug => 'confirmation_success', :pagetype => 'pagelink',
|
181
|
+
:link => 'index', :published => true, :title => 'Confirmaton Success')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# {todo} currently, this mostly works from the console. However, when run
|
186
|
+
# from the browser it hangs in some type of infinite loop, inside amoeba_dup.
|
187
|
+
# Was unable to track it down, so this function is currently not called anywhere.
|
188
|
+
#------------------------------------------------------------------------------
|
189
|
+
def duplicate_with_associations
|
190
|
+
new_page = nil
|
191
|
+
new_slug = "duplicate-#{self.slug}"
|
192
|
+
if CmsPage.find_by_slug(new_slug)
|
193
|
+
#--- already a duplicate page, return nil
|
194
|
+
return nil
|
195
|
+
else
|
196
|
+
CmsPage.paper_trail_off!
|
197
|
+
CmsContentitem.paper_trail_off!
|
198
|
+
CmsPage::Translation.paper_trail_off!
|
199
|
+
CmsContentitem::Translation.paper_trail_off!
|
200
|
+
new_page = self.amoeba_dup
|
201
|
+
new_page.slug = new_slug
|
202
|
+
# new_page.without_versioning do
|
203
|
+
new_page.save
|
204
|
+
# end
|
205
|
+
CmsPage.paper_trail_on!
|
206
|
+
CmsContentitem.paper_trail_on!
|
207
|
+
CmsPage::Translation.paper_trail_on!
|
208
|
+
CmsContentitem::Translation.paper_trail_on!
|
209
|
+
# new_page = self.initialize_dup(self)
|
210
|
+
# new_page.slug = new_slug
|
211
|
+
#
|
212
|
+
# DmCore::Language.language_array.each do |locale|
|
213
|
+
# new_page.send("title_#{locale}=", self.send("title_#{locale}")) unless self.send("title_#{locale}").nil?
|
214
|
+
# new_page.send("menutitle_#{locale}=", self.send("menutitle_#{locale}")) unless self.send("menutitle_#{locale}").nil?
|
215
|
+
# new_page.save
|
216
|
+
# end
|
217
|
+
# # new_page.save
|
218
|
+
# new_page.reload
|
219
|
+
#
|
220
|
+
# # cms_contentitems.each do |content|
|
221
|
+
# # content.deep_clone(new_page.id)
|
222
|
+
# # end
|
223
|
+
end
|
224
|
+
return new_page
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|