From d7ab03b1c74aab3b23f0cbd0da2a28c905f344fb Mon Sep 17 00:00:00 2001 From: Amine Ben hammou Date: Tue, 22 May 2018 06:52:37 +0000 Subject: [PATCH 01/12] rewrite PostTransformer to return old or new structure depending on the newVersion attribute --- .../js/src/newsletter_editor/blocks/posts.js | 1 + lib/Newsletter/Editor/LayoutHelper.php | 20 ++ lib/Newsletter/Editor/PostListTransformer.php | 2 +- lib/Newsletter/Editor/PostTransformer.php | 275 +++++++++++------- 4 files changed, 185 insertions(+), 113 deletions(-) create mode 100644 lib/Newsletter/Editor/LayoutHelper.php diff --git a/assets/js/src/newsletter_editor/blocks/posts.js b/assets/js/src/newsletter_editor/blocks/posts.js index 7c0b926e9a..43e2f164c4 100644 --- a/assets/js/src/newsletter_editor/blocks/posts.js +++ b/assets/js/src/newsletter_editor/blocks/posts.js @@ -583,6 +583,7 @@ define([ }); Module.PostsWidgetView = base.WidgetView.extend({ + className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block', getTemplate: function () { return window.templates.postsInsertion; }, behaviors: { DraggableBehavior: { diff --git a/lib/Newsletter/Editor/LayoutHelper.php b/lib/Newsletter/Editor/LayoutHelper.php new file mode 100644 index 0000000000..3d71384143 --- /dev/null +++ b/lib/Newsletter/Editor/LayoutHelper.php @@ -0,0 +1,20 @@ + 'container', + 'orientation' => 'horizontal', + 'blocks' => $blocks + ); + } + + static function col($blocks) { + return array( + 'type' => 'container', + 'orientation' => 'vertical', + 'blocks' => $blocks + ); + } +} \ No newline at end of file diff --git a/lib/Newsletter/Editor/PostListTransformer.php b/lib/Newsletter/Editor/PostListTransformer.php index 0cd44f71c4..622905e00f 100644 --- a/lib/Newsletter/Editor/PostListTransformer.php +++ b/lib/Newsletter/Editor/PostListTransformer.php @@ -18,7 +18,7 @@ class PostListTransformer { foreach($posts as $index => $post) { if($use_divider && $index > 0) { - $results[] = $this->args['divider']; + $results[] = $this->transformer->getDivider(); } $results = array_merge($results, $this->transformer->transform($post)); diff --git a/lib/Newsletter/Editor/PostTransformer.php b/lib/Newsletter/Editor/PostTransformer.php index 436bb29914..9d37eea7ef 100644 --- a/lib/Newsletter/Editor/PostTransformer.php +++ b/lib/Newsletter/Editor/PostTransformer.php @@ -4,16 +4,117 @@ namespace MailPoet\Newsletter\Editor; use MailPoet\Newsletter\Editor\PostContentManager; use MailPoet\Newsletter\Editor\MetaInformationManager; use MailPoet\Newsletter\Editor\StructureTransformer; +use MailPoet\Newsletter\Editor\LayoutHelper; if(!defined('ABSPATH')) exit; class PostTransformer { + private $args; + private $imagePosition; + function __construct($args) { $this->args = $args; + $this->imagePosition = 'left'; + } + + function getDivider() { + if (empty($this->args['withLayout'])) { + return $this->args['divider']; + } + return LayoutHelper::row(array( + LayoutHelper::col(array($this->args['divider'])) + )); } function transform($post) { + if (empty($this->args['withLayout'])) { + return $this->getOldStructure($post); + } + return $this->getNewStructure($post); + } + + private function getOldStructure($post) { + $content = $this->getContent($post); + $title = $this->getTitle($post); + $featured_image = $this->getFeaturedImage($post); + + $image_position = $this->args['featuredImagePosition']; + + if($featured_image && $image_position === 'belowTitle') { + array_unshift($content, $title, $featured_image); + } else { + if($content[0]['type'] === 'text') { + $content[0]['text'] .= $title['text']; + } else { + array_unshift($content, $title); + } + if($featured_image) { + array_unshift($content, $featured_image); + } + } + + return $content; + } + + private function getNewStructure($post) { + $content = $this->getContent($post); + $title = $this->getTitle($post); + $featured_image = $this->getFeaturedImage($post); + + $position = $this->args['featuredImagePosition']; + + if(!$featured_image || $position === 'none' || $this->args['displayType'] !== 'excerpt') { + array_unshift($content, $title); + + return array( + LayoutHelper::row(array( + LayoutHelper::col($content) + )) + ); + } + + if($position === 'aboveTitle' || $position === 'belowTitle') { + $position = 'centered'; + } + + if($position === 'centered') { + array_unshift($content, $title, $featured_image); + return array( + LayoutHelper::row(array( + LayoutHelper::col($content) + )) + ); + } + + if($position === 'alternate') { + $position = $this->nextImagePosition(); + } + + $content = ($position === 'left') + ? array( + LayoutHelper::col(array($featured_image)), + LayoutHelper::col($content) + ) + : array( + LayoutHelper::col($content), + LayoutHelper::col(array($featured_image)) + ); + + return array( + LayoutHelper::row(array( + LayoutHelper::col(array($title)) + )), + LayoutHelper::row($content) + ); + } + + private function nextImagePosition() { + $this->imagePosition = ($this->imagePosition === 'left') ? 'right' : 'left'; + return $this->imagePosition; + } + + private function getContent($post) { $content_manager = new PostContentManager(); $meta_manager = new MetaInformationManager(); @@ -22,137 +123,82 @@ class PostTransformer { $content = $content_manager->filterContent($content); $structure_transformer = new StructureTransformer(); - $structure = $structure_transformer->transform($content, $this->args['imageFullWidth'] === true); + $content = $structure_transformer->transform($content, $this->args['imageFullWidth'] === true); - if($this->args['featuredImagePosition'] === 'aboveTitle') { - $structure = $this->appendPostTitle($post, $structure); - $structure = $this->appendFeaturedImage( - $post, - $this->args['displayType'], - filter_var($this->args['imageFullWidth'], FILTER_VALIDATE_BOOLEAN), - $structure - ); + $read_more_btn = $this->getReadMoreButton($post); + $blocks_count = count($content); + if($read_more_btn['type'] === 'text' && $blocks_count > 0 && $content[$blocks_count - 1]['type'] === 'text') { + $content[$blocks_count - 1]['text'] .= $read_more_btn['text']; } else { - if($this->args['featuredImagePosition'] === 'belowTitle') { - $structure = $this->appendFeaturedImage( - $post, - $this->args['displayType'], - filter_var($this->args['imageFullWidth'], FILTER_VALIDATE_BOOLEAN), - $structure - ); - } - $structure = $this->appendPostTitle($post, $structure); + $content[] = $read_more_btn; } - $structure = $this->appendReadMore($post->ID, $structure); - - return $structure; + return $content; } - private function appendFeaturedImage($post, $display_type, $image_full_width, $structure) { - if($display_type !== 'excerpt') { - // Append featured images only on excerpts - return $structure; + private function getFeaturedImage($post) { + $post_id = $post->ID; + $post_title = $post->post_title; + $image_full_width = (bool)filter_var($this->args['imageFullWidth'], FILTER_VALIDATE_BOOLEAN); + + if(!has_post_thumbnail($post_id)) { + return false; } - $featured_image = $this->getFeaturedImage( - $post->ID, - $post->post_title, - (bool)$image_full_width + $thumbnail_id = get_post_thumbnail_id($post_id); + + // get attachment data (src, width, height) + $image_info = wp_get_attachment_image_src( + $thumbnail_id, + 'mailpoet_newsletter_max' ); - if(is_array($featured_image)) { - return array_merge(array($featured_image), $structure); + // get alt text + $alt_text = trim(strip_tags(get_post_meta( + $thumbnail_id, + '_wp_attachment_image_alt', + true + ))); + if(strlen($alt_text) === 0) { + // if the alt text is empty then use the post title + $alt_text = trim(strip_tags($post_title)); } - return $structure; - } - - private function getFeaturedImage($post_id, $post_title, $image_full_width) { - if(has_post_thumbnail($post_id)) { - $thumbnail_id = get_post_thumbnail_id($post_id); - - // get attachment data (src, width, height) - $image_info = wp_get_attachment_image_src( - $thumbnail_id, - 'mailpoet_newsletter_max' - ); - - // get alt text - $alt_text = trim(strip_tags(get_post_meta( - $thumbnail_id, - '_wp_attachment_image_alt', - true - ))); - if(strlen($alt_text) === 0) { - // if the alt text is empty then use the post title - $alt_text = trim(strip_tags($post_title)); - } - - return array( - 'type' => 'image', - 'link' => get_permalink($post_id), - 'src' => $image_info[0], - 'alt' => $alt_text, - 'fullWidth' => $image_full_width, - 'width' => $image_info[1], - 'height' => $image_info[2], - 'styles' => array( - 'block' => array( - 'textAlign' => 'center', - ), + return array( + 'type' => 'image', + 'link' => get_permalink($post_id), + 'src' => $image_info[0], + 'alt' => $alt_text, + 'fullWidth' => $image_full_width, + 'width' => $image_info[1], + 'height' => $image_info[2], + 'styles' => array( + 'block' => array( + 'textAlign' => 'center', ), - ); - } + ), + ); } - private function appendPostTitle($post, $structure) { - $title = $this->getPostTitle($post); - - // Append title always at the top of the post structure - // Reuse an existing text block if needed - - if(count($structure) > 0 && $structure[0]['type'] === 'text') { - $structure[0]['text'] = $title . $structure[0]['text']; - } else { - array_unshift( - $structure, - array( - 'type' => 'text', - 'text' => $title, - ) - ); - } - - return $structure; - } - - private function appendReadMore($post_id, $structure) { + private function getReadMoreButton($post) { if($this->args['readMoreType'] === 'button') { $button = $this->args['readMoreButton']; - $button['url'] = get_permalink($post_id); - $structure[] = $button; - } else { - $total_blocks = count($structure); - $read_more_text = sprintf( - '

%s

', - get_permalink($post_id), - $this->args['readMoreText'] - ); - - if($structure[$total_blocks - 1]['type'] === 'text') { - $structure[$total_blocks - 1]['text'] .= $read_more_text; - } else { - $structure[] = array( - 'type' => 'text', - 'text' => $read_more_text, - ); - } + $button['url'] = get_permalink($post->ID); + return $button; } - return $structure; + $read_more_text = sprintf( + '

%s

', + get_permalink($post->ID), + $this->args['readMoreText'] + ); + + return array( + 'type' => 'text', + 'text' => $read_more_text, + ); } - private function getPostTitle($post) { + private function getTitle($post) { $title = $post->post_title; if(filter_var($this->args['titleIsLink'], FILTER_VALIDATE_BOOLEAN)) { @@ -169,6 +215,11 @@ class PostTransformer { $alignment = (in_array($this->args['titleAlignment'], array('left', 'right', 'center'))) ? $this->args['titleAlignment'] : 'left'; - return '<' . $tag . ' data-post-id="' . $post->ID . '" style="text-align: ' . $alignment . ';">' . $title . ''; + $title = '<' . $tag . ' data-post-id="' . $post->ID . '" style="text-align: ' . $alignment . ';">' . $title . ''; + return array( + 'type' => 'text', + 'text' => $title + ); } + } From 4dd17e47ad453f95aa86abebe9e9675eb2f72a3f Mon Sep 17 00:00:00 2001 From: Amine Ben hammou Date: Wed, 23 May 2018 05:17:51 +0000 Subject: [PATCH 02/12] add image alignment to Posts --- .../contentBlocks/container.styl | 3 ++- .../contentBlocks/posts.styl | 3 +++ .../src/newsletter_editor/blocks/container.js | 2 +- .../js/src/newsletter_editor/blocks/posts.js | 5 +++-- .../templates/blocks/posts/block.hbs | 4 +--- .../blocks/posts/settingsDisplayOptions.hbs | 20 +++++++++++++++---- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/assets/css/src/newsletter_editor/contentBlocks/container.styl b/assets/css/src/newsletter_editor/contentBlocks/container.styl index cc59536c24..77c1527a09 100644 --- a/assets/css/src/newsletter_editor/contentBlocks/container.styl +++ b/assets/css/src/newsletter_editor/contentBlocks/container.styl @@ -52,7 +52,8 @@ $three-column-width = ($newsletter-width / 3) - (2 * $column-margin) width: $column-margin + $one-column-width + $column-margin // More than one column - & > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal + & > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal, + & > .mailpoet_container_block > .mailpoet_container > .mailpoet_posts_block > .mailpoet_posts_container > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal // Column number detection technique found here: // http://stackoverflow.com/questions/8720931/can-css-detect-the-number-of-children-an-element-has diff --git a/assets/css/src/newsletter_editor/contentBlocks/posts.styl b/assets/css/src/newsletter_editor/contentBlocks/posts.styl index 25094c90ba..1dc7e86dbc 100644 --- a/assets/css/src/newsletter_editor/contentBlocks/posts.styl +++ b/assets/css/src/newsletter_editor/contentBlocks/posts.styl @@ -54,3 +54,6 @@ .mailpoet_post_selection_loading color: #999 + +.mailpoet_posts_container > .mailpoet_droppable_block + width: 100% diff --git a/assets/js/src/newsletter_editor/blocks/container.js b/assets/js/src/newsletter_editor/blocks/container.js index 3be7a76c30..0843fee878 100644 --- a/assets/js/src/newsletter_editor/blocks/container.js +++ b/assets/js/src/newsletter_editor/blocks/container.js @@ -59,7 +59,7 @@ define([ }, parse: function (response) { // If container has any blocks - add them to a collection - if (response.type === 'container' && _.has(response, 'blocks')) { + if (response.type === 'container' && _.has(response, 'blocks') && response.blocks.constructor === Array) { response.blocks = new BlockCollection(response.blocks, { parse: true }); diff --git a/assets/js/src/newsletter_editor/blocks/posts.js b/assets/js/src/newsletter_editor/blocks/posts.js index 43e2f164c4..7544f18a4c 100644 --- a/assets/js/src/newsletter_editor/blocks/posts.js +++ b/assets/js/src/newsletter_editor/blocks/posts.js @@ -52,6 +52,7 @@ define([ defaults: function () { return this._getDefaults({ type: 'posts', + withLayout: true, amount: '10', offset: 0, contentType: 'post', // 'post'|'page'|'mailpoet_page' @@ -64,7 +65,7 @@ define([ titleAlignment: 'left', // 'left'|'center'|'right' titleIsLink: false, // false|true imageFullWidth: false, // true|false - featuredImagePosition: 'belowTitle', // 'aboveTitle'|'belowTitle'|'none' + featuredImagePosition: 'centered', // 'centered'|'right'|'left'|'alternate'|'none' showAuthor: 'no', // 'no'|'aboveText'|'belowText' authorPrecededBy: 'Author:', showCategories: 'no', // 'no'|'aboveText'|'belowText' @@ -190,7 +191,7 @@ define([ getTemplate: function () { return window.templates.postsBlock; }, modelEvents: {}, // Forcefully disable all events regions: _.extend({ - postsRegion: '.mailpoet_posts_block_posts' + postsRegion: '.mailpoet_posts_container' }, base.BlockView.prototype.regions), onDragSubstituteBy: function () { return Module.PostsWidgetView; }, initialize: function () { diff --git a/views/newsletter/templates/blocks/posts/block.hbs b/views/newsletter/templates/blocks/posts/block.hbs index 2d6297c5ed..a3c837e650 100644 --- a/views/newsletter/templates/blocks/posts/block.hbs +++ b/views/newsletter/templates/blocks/posts/block.hbs @@ -1,5 +1,3 @@
-
-
-
+
diff --git a/views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs b/views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs index 6ce983d3be..99089a449c 100644 --- a/views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs +++ b/views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs @@ -95,14 +95,26 @@
<%= __('Featured image position') %>
+
+
+ +
+
+
From 0a298f5fad0fab6044c9e9550fd376d79079a6d0 Mon Sep 17 00:00:00 2001 From: Amine Ben hammou Date: Wed, 23 May 2018 07:37:34 +0000 Subject: [PATCH 03/12] creating new ALC block and widget --- .../contentBlocks/container.styl | 3 +- .../blocks/automatedLatestContent.js | 7 +- .../blocks/automatedLatestContentLayout.js | 400 ++++++++++++++++++ lib/Newsletter/Editor/PostTransformer.php | 16 +- lib/Newsletter/Renderer/Blocks/Renderer.php | 12 +- lib/Newsletter/Renderer/Renderer.php | 21 + views/newsletter/editor.html | 79 ++++ .../automatedLatestContentLayout/block.hbs | 6 + .../automatedLatestContentLayout/settings.hbs | 313 ++++++++++++++ .../automatedLatestContentLayout/widget.hbs | 4 + webpack.config.js | 2 + 11 files changed, 845 insertions(+), 18 deletions(-) create mode 100644 assets/js/src/newsletter_editor/blocks/automatedLatestContentLayout.js create mode 100644 views/newsletter/templates/blocks/automatedLatestContentLayout/block.hbs create mode 100644 views/newsletter/templates/blocks/automatedLatestContentLayout/settings.hbs create mode 100644 views/newsletter/templates/blocks/automatedLatestContentLayout/widget.hbs diff --git a/assets/css/src/newsletter_editor/contentBlocks/container.styl b/assets/css/src/newsletter_editor/contentBlocks/container.styl index 77c1527a09..07fbf4b461 100644 --- a/assets/css/src/newsletter_editor/contentBlocks/container.styl +++ b/assets/css/src/newsletter_editor/contentBlocks/container.styl @@ -53,7 +53,8 @@ $three-column-width = ($newsletter-width / 3) - (2 * $column-margin) // More than one column & > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal, - & > .mailpoet_container_block > .mailpoet_container > .mailpoet_posts_block > .mailpoet_posts_container > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal + & > .mailpoet_container_block > .mailpoet_container > .mailpoet_posts_block > .mailpoet_posts_container > .mailpoet_container_block > .mailpoet_container > .mailpoet_container_block > .mailpoet_container_horizontal, + & > .mailpoet_container_block > .mailpoet_container .mailpoet_automated_latest_content_block_posts .mailpoet_container_horizontal // Column number detection technique found here: // http://stackoverflow.com/questions/8720931/can-css-detect-the-number-of-children-an-element-has diff --git a/assets/js/src/newsletter_editor/blocks/automatedLatestContent.js b/assets/js/src/newsletter_editor/blocks/automatedLatestContent.js index d2948fe1b0..c240096d2d 100644 --- a/assets/js/src/newsletter_editor/blocks/automatedLatestContent.js +++ b/assets/js/src/newsletter_editor/blocks/automatedLatestContent.js @@ -74,6 +74,7 @@ define([ defaults: function () { return this._getDefaults({ type: 'automatedLatestContent', + withLayout: false, amount: '5', contentType: 'post', // 'post'|'page'|'mailpoet_page' terms: [], // List of category and tag objects @@ -385,12 +386,6 @@ define([ blockModel: Module.AutomatedLatestContentBlockModel, blockView: Module.AutomatedLatestContentBlockView }); - - BeforeStartApp.registerWidget({ - name: 'automatedLatestContent', - widgetView: Module.AutomatedLatestContentWidgetView, - priority: 97 - }); }); App.on('start', function (StartApp) { diff --git a/assets/js/src/newsletter_editor/blocks/automatedLatestContentLayout.js b/assets/js/src/newsletter_editor/blocks/automatedLatestContentLayout.js new file mode 100644 index 0000000000..3737ec6f47 --- /dev/null +++ b/assets/js/src/newsletter_editor/blocks/automatedLatestContentLayout.js @@ -0,0 +1,400 @@ +/* eslint-disable func-names */ +/** + * Automated latest content block with image alignment. + */ +define([ + 'newsletter_editor/App', + 'newsletter_editor/blocks/base', + 'newsletter_editor/blocks/button', + 'newsletter_editor/blocks/divider', + 'newsletter_editor/components/communication', + 'mailpoet', + 'backbone.supermodel', + 'underscore', + 'jquery' +], function ( + App, + BaseBlock, + ButtonBlock, + DividerBlock, + CommunicationComponent, + MailPoet, + SuperModel, + _, + jQuery + ) { + 'use strict'; + + var Module = {}; + var base = BaseBlock; + + Module.ALCLayoutSupervisor = SuperModel.extend({ + initialize: function () { + var DELAY_REFRESH_FOR_MS = 500; + this.listenTo( + App.getChannel(), + 'automatedLatestContentLayoutRefresh', + _.debounce(this.refresh, DELAY_REFRESH_FOR_MS) + ); + }, + refresh: function () { + var blocks; + var models = App.findModels(function (model) { + return model.get('type') === 'automatedLatestContentLayout'; + }) || []; + + if (models.length === 0) return; + blocks = _.map(models, function (model) { + return model.toJSON(); + }); + + CommunicationComponent.getBulkTransformedPosts({ + blocks: blocks + }).then(_.partial(this.refreshBlocks, models)); + }, + refreshBlocks: function (models, renderedBlocks) { + _.each( + _.zip(models, renderedBlocks), + function (args) { + var model = args[0]; + var contents = args[1]; + model.trigger('refreshPosts', contents); + } + ); + } + }); + + Module.AutomatedLatestContentLayoutBlockModel = base.BlockModel.extend({ + stale: ['_container'], + defaults: function () { + return this._getDefaults({ + type: 'automatedLatestContentLayout', + withLayout: true, + amount: '5', + contentType: 'post', // 'post'|'page'|'mailpoet_page' + terms: [], // List of category and tag objects + inclusionType: 'include', // 'include'|'exclude' + displayType: 'excerpt', // 'excerpt'|'full'|'titleOnly' + titleFormat: 'h1', // 'h1'|'h2'|'h3'|'ul' + titleAlignment: 'left', // 'left'|'center'|'right' + titleIsLink: false, // false|true + imageFullWidth: false, // true|false + featuredImagePosition: 'centered', // 'centered'|'left'|'right'|'alternate'|'none' + showAuthor: 'no', // 'no'|'aboveText'|'belowText' + authorPrecededBy: 'Author:', + showCategories: 'no', // 'no'|'aboveText'|'belowText' + categoriesPrecededBy: 'Categories:', + readMoreType: 'button', // 'link'|'button' + readMoreText: 'Read more', // 'link'|'button' + readMoreButton: { + text: 'Read more', + url: '[postLink]' + }, + sortBy: 'newest', // 'newest'|'oldest', + showDivider: true, // true|false + divider: {}, + _container: new (App.getBlockTypeModel('container'))() + }, App.getConfig().get('blockDefaults.automatedLatestContentLayout')); + }, + relations: function () { + return { + readMoreButton: App.getBlockTypeModel('button'), + divider: App.getBlockTypeModel('divider'), + _container: App.getBlockTypeModel('container') + }; + }, + initialize: function () { + base.BlockView.prototype.initialize.apply(this, arguments); + this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:featuredImagePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._handleChanges, this); + this.listenTo(this.get('readMoreButton'), 'change', this._handleChanges); + this.listenTo(this.get('divider'), 'change', this._handleChanges); + this.on('add remove update reset', this._handleChanges); + this.on('refreshPosts', this.updatePosts, this); + }, + updatePosts: function (posts) { + this.get('_container.blocks').reset(posts, { parse: true }); + }, + /** + * Batch more changes during a specific time, instead of fetching + * ALC posts on each model change + */ + _handleChanges: function () { + this._updateDefaults(); + App.getChannel().trigger('automatedLatestContentLayoutRefresh'); + } + }); + + Module.AutomatedLatestContentLayoutBlockView = base.BlockView.extend({ + className: 'mailpoet_block mailpoet_automated_latest_content_block mailpoet_droppable_block', + initialize: function () { + function replaceButtonStylesHandler(data) { + this.model.set({ readMoreButton: data }); + } + App.getChannel().on('replaceAllButtonStyles', replaceButtonStylesHandler.bind(this)); + }, + getTemplate: function () { return window.templates.automatedLatestContentLayoutBlock; }, + regions: { + toolsRegion: '.mailpoet_tools', + postsRegion: '.mailpoet_automated_latest_content_block_posts' + }, + modelEvents: _.extend( + _.omit(base.BlockView.prototype.modelEvents, 'change'), + { + postsChanged: 'render' + }), + events: _.extend(base.BlockView.prototype.events, { + 'click .mailpoet_automated_latest_content_block_overlay': 'showSettings' + }), + onDragSubstituteBy: function () { return Module.AutomatedLatestContentLayoutWidgetView; }, + onRender: function () { + var ContainerView = App.getBlockTypeView('container'); + var renderOptions = { + disableTextEditor: true, + disableDragAndDrop: true, + emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay') + }; + this.toolsView = new Module.AutomatedLatestContentLayoutBlockToolsView({ model: this.model }); + this.showChildView('toolsRegion', this.toolsView); + this.showChildView('postsRegion', new ContainerView({ model: this.model.get('_container'), renderOptions: renderOptions })); + } + }); + + Module.AutomatedLatestContentLayoutBlockToolsView = base.BlockToolsView.extend({ + getSettingsView: function () { return Module.AutomatedLatestContentLayoutBlockSettingsView; } + }); + + // Sidebar view container + Module.AutomatedLatestContentLayoutBlockSettingsView = base.BlockSettingsView.extend({ + getTemplate: function () { return window.templates.automatedLatestContentLayoutBlockSettings; }, + events: function () { + return { + 'click .mailpoet_automated_latest_content_hide_display_options': 'toggleDisplayOptions', + 'click .mailpoet_automated_latest_content_show_display_options': 'toggleDisplayOptions', + 'click .mailpoet_automated_latest_content_select_button': 'showButtonSettings', + 'click .mailpoet_automated_latest_content_select_divider': 'showDividerSettings', + 'change .mailpoet_automated_latest_content_read_more_type': 'changeReadMoreType', + 'change .mailpoet_automated_latest_content_display_type': 'changeDisplayType', + 'change .mailpoet_automated_latest_content_title_format': 'changeTitleFormat', + 'change .mailpoet_automated_latest_content_title_as_links': _.partial(this.changeBoolField, 'titleIsLink'), + 'change .mailpoet_automated_latest_content_show_divider': _.partial(this.changeBoolField, 'showDivider'), + 'input .mailpoet_automated_latest_content_show_amount': _.partial(this.changeField, 'amount'), + 'change .mailpoet_automated_latest_content_content_type': _.partial(this.changeField, 'contentType'), + 'change .mailpoet_automated_latest_content_include_or_exclude': _.partial(this.changeField, 'inclusionType'), + 'change .mailpoet_automated_latest_content_title_alignment': _.partial(this.changeField, 'titleAlignment'), + 'change .mailpoet_automated_latest_content_image_full_width': _.partial(this.changeBoolField, 'imageFullWidth'), + 'change .mailpoet_automated_latest_content_featured_image_position': _.partial(this.changeField, 'featuredImagePosition'), + 'change .mailpoet_automated_latest_content_show_author': _.partial(this.changeField, 'showAuthor'), + 'input .mailpoet_automated_latest_content_author_preceded_by': _.partial(this.changeField, 'authorPrecededBy'), + 'change .mailpoet_automated_latest_content_show_categories': _.partial(this.changeField, 'showCategories'), + 'input .mailpoet_automated_latest_content_categories': _.partial(this.changeField, 'categoriesPrecededBy'), + 'input .mailpoet_automated_latest_content_read_more_text': _.partial(this.changeField, 'readMoreText'), + 'change .mailpoet_automated_latest_content_sort_by': _.partial(this.changeField, 'sortBy'), + 'click .mailpoet_done_editing': 'close' + }; + }, + onRender: function () { + var that = this; + + // Dynamically update available post types + CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this)); + + this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({ + multiple: true, + allowClear: true, + placeholder: MailPoet.I18n.t('categoriesAndTags'), + ajax: { + data: function (params) { + return { + term: params.term + }; + }, + transport: function (options, success, failure) { + var taxonomies; + var termsPromise; + var promise = CommunicationComponent.getTaxonomies( + that.model.get('contentType') + ).then(function (tax) { + taxonomies = tax; + // Fetch available terms based on the list of taxonomies already fetched + termsPromise = CommunicationComponent.getTerms({ + search: options.data.term, + taxonomies: _.keys(taxonomies) + }).then(function (terms) { + return { + taxonomies: taxonomies, + terms: terms + }; + }); + return termsPromise; + }); + + promise.then(success); + promise.fail(failure); + return promise; + }, + processResults: function (data) { + // Transform taxonomies and terms into select2 compatible format + return { + results: _.map( + data.terms, + function (item) { + return _.defaults({ + text: data.taxonomies[item.taxonomy].labels.singular_name + ': ' + item.name, + id: item.term_id + }, item); + } + ) + }; + } + } + }).on({ + 'select2:select': function (event) { + var terms = that.model.get('terms'); + terms.add(event.params.data); + // Reset whole model in order for change events to propagate properly + that.model.set('terms', terms.toJSON()); + }, + 'select2:unselect': function (event) { + var terms = that.model.get('terms'); + terms.remove(event.params.data); + // Reset whole model in order for change events to propagate properly + that.model.set('terms', terms.toJSON()); + } + }).trigger('change'); + }, + toggleDisplayOptions: function () { + var el = this.$('.mailpoet_automated_latest_content_display_options'); + var showControl = this.$('.mailpoet_automated_latest_content_show_display_options'); + if (el.hasClass('mailpoet_closed')) { + el.removeClass('mailpoet_closed'); + showControl.addClass('mailpoet_hidden'); + } else { + el.addClass('mailpoet_closed'); + showControl.removeClass('mailpoet_hidden'); + } + }, + showButtonSettings: function () { + var buttonModule = ButtonBlock; + (new buttonModule.ButtonBlockSettingsView({ + model: this.model.get('readMoreButton'), + renderOptions: { + displayFormat: 'subpanel', + hideLink: true, + hideApplyToAll: true + } + })).render(); + }, + showDividerSettings: function () { + var dividerModule = DividerBlock; + (new dividerModule.DividerBlockSettingsView({ + model: this.model.get('divider'), + renderOptions: { + displayFormat: 'subpanel', + hideApplyToAll: true + } + })).render(); + }, + changeReadMoreType: function (event) { + var value = jQuery(event.target).val(); + if (value === 'link') { + this.$('.mailpoet_automated_latest_content_read_more_text').removeClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_select_button').addClass('mailpoet_hidden'); + } else if (value === 'button') { + this.$('.mailpoet_automated_latest_content_read_more_text').addClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_select_button').removeClass('mailpoet_hidden'); + } + this.changeField('readMoreType', event); + }, + changeDisplayType: function (event) { + var value = jQuery(event.target).val(); + + if (value === 'titleOnly') { + this.$('.mailpoet_automated_latest_content_title_as_list').removeClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_image_full_width_option').addClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_image_separator').addClass('mailpoet_hidden'); + } else { + this.$('.mailpoet_automated_latest_content_title_as_list').addClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_image_full_width_option').removeClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_image_separator').removeClass('mailpoet_hidden'); + + // Reset titleFormat if it was set to List when switching away from displayType=titleOnly + if (this.model.get('titleFormat') === 'ul') { + this.model.set('titleFormat', 'h1'); + this.$('.mailpoet_automated_latest_content_title_format').val(['h1']); + this.$('.mailpoet_automated_latest_content_title_as_link').removeClass('mailpoet_hidden'); + } + } + + if (value === 'excerpt') { + this.$('.mailpoet_automated_latest_content_featured_image_position_container').removeClass('mailpoet_hidden'); + } else { + this.$('.mailpoet_automated_latest_content_featured_image_position_container').addClass('mailpoet_hidden'); + } + this.changeField('displayType', event); + }, + changeTitleFormat: function (event) { + var value = jQuery(event.target).val(); + if (value === 'ul') { + this.$('.mailpoet_automated_latest_content_non_title_list_options').addClass('mailpoet_hidden'); + + this.model.set('titleIsLink', true); + this.$('.mailpoet_automated_latest_content_title_as_link').addClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_title_as_links').val(['true']); + } else { + this.$('.mailpoet_automated_latest_content_non_title_list_options').removeClass('mailpoet_hidden'); + this.$('.mailpoet_automated_latest_content_title_as_link').removeClass('mailpoet_hidden'); + } + this.changeField('titleFormat', event); + }, + _updateContentTypes: function (postTypes) { + var select = this.$('.mailpoet_automated_latest_content_content_type'); + var selectedValue = this.model.get('contentType'); + + select.find('option').remove(); + _.each(postTypes, function (type) { + select.append(jQuery('