Merge pull request #965 from mailpoet/posts_dynamic_loading
Add dynamic post loading in Posts widget settings [MAILPOET-971]
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
.mailpoet_settings_posts_display_options
|
.mailpoet_settings_posts_display_options
|
||||||
.mailpoet_settings_posts_selection
|
.mailpoet_settings_posts_selection
|
||||||
animation-slide-open-downwards()
|
animation-slide-open-downwards()
|
||||||
|
overflow-x: hidden
|
||||||
|
|
||||||
.mailpoet_settings_posts_show_display_options,
|
.mailpoet_settings_posts_show_display_options,
|
||||||
.mailpoet_settings_posts_show_post_selection
|
.mailpoet_settings_posts_show_post_selection
|
||||||
@@ -26,7 +27,12 @@
|
|||||||
|
|
||||||
.mailpoet_post_selection_container
|
.mailpoet_post_selection_container
|
||||||
margin-top: 20px
|
margin-top: 20px
|
||||||
margin-bottom: 20px
|
margin-bottom: 0
|
||||||
|
|
||||||
|
.mailpoet_post_scroll_container
|
||||||
|
overflow-y: scroll
|
||||||
|
overflow-x: hidden
|
||||||
|
max-height: 400px
|
||||||
|
|
||||||
.mailpoet_settings_posts_single_post
|
.mailpoet_settings_posts_single_post
|
||||||
border-radius(1px)
|
border-radius(1px)
|
||||||
@@ -45,3 +51,6 @@
|
|||||||
.mailpoet_select_post_checkbox
|
.mailpoet_select_post_checkbox
|
||||||
margin-left: 10px
|
margin-left: 10px
|
||||||
margin-right: 8px
|
margin-right: 8px
|
||||||
|
|
||||||
|
.mailpoet_post_selection_loading
|
||||||
|
color: #999
|
||||||
|
@@ -48,6 +48,7 @@ define([
|
|||||||
return this._getDefaults({
|
return this._getDefaults({
|
||||||
type: 'posts',
|
type: 'posts',
|
||||||
amount: '10',
|
amount: '10',
|
||||||
|
offset: 0,
|
||||||
contentType: 'post', // 'post'|'page'|'mailpoet_page'
|
contentType: 'post', // 'post'|'page'|'mailpoet_page'
|
||||||
postStatus: 'publish', // 'draft'|'pending'|'private'|'publish'|'future'
|
postStatus: 'publish', // 'draft'|'pending'|'private'|'publish'|'future'
|
||||||
terms: [], // List of category and tag objects
|
terms: [], // List of category and tag objects
|
||||||
@@ -98,6 +99,7 @@ define([
|
|||||||
|
|
||||||
this.fetchAvailablePosts();
|
this.fetchAvailablePosts();
|
||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
||||||
|
this.on('loadMorePosts', this._loadMorePosts, this);
|
||||||
|
|
||||||
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
||||||
this.on('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:showDivider', refreshTransformedPosts);
|
this.on('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:showDivider', refreshTransformedPosts);
|
||||||
@@ -108,6 +110,7 @@ define([
|
|||||||
},
|
},
|
||||||
fetchAvailablePosts: function() {
|
fetchAvailablePosts: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
this.set('offset', 0);
|
||||||
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||||
that.get('_availablePosts').reset(posts);
|
that.get('_availablePosts').reset(posts);
|
||||||
that.get('_selectedPosts').reset(); // Empty out the collection
|
that.get('_selectedPosts').reset(); // Empty out the collection
|
||||||
@@ -116,6 +119,27 @@ define([
|
|||||||
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchAvailablePosts'));
|
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchAvailablePosts'));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
_loadMorePosts: function() {
|
||||||
|
var that = this,
|
||||||
|
postCount = this.get('_availablePosts').length,
|
||||||
|
nextOffset = this.get('offset') + Number(this.get('amount'));
|
||||||
|
|
||||||
|
if(postCount === 0 || postCount < nextOffset) {
|
||||||
|
// No more posts to load
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.set('offset', nextOffset);
|
||||||
|
this.trigger('loadingMorePosts');
|
||||||
|
|
||||||
|
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||||
|
that.get('_availablePosts').add(posts);
|
||||||
|
that.trigger('change:_availablePosts');
|
||||||
|
}).fail(function() {
|
||||||
|
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchAvailablePosts'));
|
||||||
|
}).always(function() {
|
||||||
|
that.trigger('morePostsLoaded');
|
||||||
|
});
|
||||||
|
},
|
||||||
_refreshTransformedPosts: function() {
|
_refreshTransformedPosts: function() {
|
||||||
var that = this,
|
var that = this,
|
||||||
data = this.toJSON();
|
data = this.toJSON();
|
||||||
@@ -260,6 +284,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
var PostsSelectionCollectionView = Marionette.CollectionView.extend({
|
var PostsSelectionCollectionView = Marionette.CollectionView.extend({
|
||||||
|
className: 'mailpoet_post_scroll_container',
|
||||||
childView: function() { return SinglePostSelectionSettingsView; },
|
childView: function() { return SinglePostSelectionSettingsView; },
|
||||||
emptyView: function() { return EmptyPostSelectionSettingsView; },
|
emptyView: function() { return EmptyPostSelectionSettingsView; },
|
||||||
childViewOptions: function() {
|
childViewOptions: function() {
|
||||||
@@ -270,6 +295,16 @@ define([
|
|||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.blockModel = options.blockModel;
|
this.blockModel = options.blockModel;
|
||||||
},
|
},
|
||||||
|
events: {
|
||||||
|
'scroll': 'onPostsScroll',
|
||||||
|
},
|
||||||
|
onPostsScroll: function(event) {
|
||||||
|
var $postsBox = jQuery(event.target);
|
||||||
|
if($postsBox.scrollTop() + $postsBox.innerHeight() >= $postsBox[0].scrollHeight){
|
||||||
|
// Load more posts if scrolled to bottom
|
||||||
|
this.blockModel.trigger('loadMorePosts');
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
var PostSelectionSettingsView = Marionette.View.extend({
|
var PostSelectionSettingsView = Marionette.View.extend({
|
||||||
@@ -284,6 +319,20 @@ define([
|
|||||||
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
modelEvents: {
|
||||||
|
'change:offset': function(model, value) {
|
||||||
|
// Scroll posts view to top if settings are changed
|
||||||
|
if (value === 0) {
|
||||||
|
this.$('.mailpoet_post_scroll_container').scrollTop(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'loadingMorePosts': function() {
|
||||||
|
this.$('.mailpoet_post_selection_loading').css('visibility', 'visible');
|
||||||
|
},
|
||||||
|
'morePostsLoaded': function() {
|
||||||
|
this.$('.mailpoet_post_selection_loading').css('visibility', 'hidden');
|
||||||
|
}
|
||||||
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
@@ -39,11 +39,15 @@ class AutomatedLatestContent {
|
|||||||
'orderby' => 'date',
|
'orderby' => 'date',
|
||||||
'order' => ($args['sortBy'] === 'newest') ? 'DESC' : 'ASC',
|
'order' => ($args['sortBy'] === 'newest') ? 'DESC' : 'ASC',
|
||||||
);
|
);
|
||||||
|
if(!empty($args['offset']) && (int)$args['offset'] > 0) {
|
||||||
|
$parameters['offset'] = (int)$args['offset'];
|
||||||
|
}
|
||||||
if(isset($args['search'])) {
|
if(isset($args['search'])) {
|
||||||
$parameters['s'] = $args['search'];
|
$parameters['s'] = $args['search'];
|
||||||
}
|
}
|
||||||
if(isset($args['posts']) && is_array($args['posts'])) {
|
if(isset($args['posts']) && is_array($args['posts'])) {
|
||||||
$parameters['post__in'] = $args['posts'];
|
$parameters['post__in'] = $args['posts'];
|
||||||
|
$parameters['posts_per_page'] = -1; // Get all posts with matching IDs
|
||||||
}
|
}
|
||||||
if(!empty($posts_to_exclude)) {
|
if(!empty($posts_to_exclude)) {
|
||||||
$parameters['post__not_in'] = $posts_to_exclude;
|
$parameters['post__not_in'] = $posts_to_exclude;
|
||||||
|
@@ -43,6 +43,10 @@ define([
|
|||||||
expect(model.get('amount')).to.match(/^\d+$/);
|
expect(model.get('amount')).to.match(/^\d+$/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('has post offset initialized', function () {
|
||||||
|
expect(model.get('offset')).to.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
it('has post type filter', function () {
|
it('has post type filter', function () {
|
||||||
expect(model.get('contentType')).to.match(/^(post|page|mailpoet_page)$/);
|
expect(model.get('contentType')).to.match(/^(post|page|mailpoet_page)$/);
|
||||||
});
|
});
|
||||||
@@ -197,6 +201,55 @@ define([
|
|||||||
expect(model.get('divider.styles.block.backgroundColor')).to.equal('#456789');
|
expect(model.get('divider.styles.block.backgroundColor')).to.equal('#456789');
|
||||||
expect(model.get('divider.styles.block.padding')).to.equal('38px');
|
expect(model.get('divider.styles.block.padding')).to.equal('38px');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('resets offset when fetching posts', function () {
|
||||||
|
model.set('offset', 10);
|
||||||
|
model.fetchAvailablePosts();
|
||||||
|
expect(model.get('offset')).to.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('increases offset when loading more posts', function () {
|
||||||
|
model.set({
|
||||||
|
amount: 2,
|
||||||
|
offset: 0
|
||||||
|
});
|
||||||
|
model.set('_availablePosts', new Backbone.Collection([{}, {}])); // 2 posts
|
||||||
|
model.trigger('loadMorePosts');
|
||||||
|
expect(model.get('offset')).to.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not increase offset when there is no more posts to load', function () {
|
||||||
|
model.set({
|
||||||
|
amount: 10,
|
||||||
|
offset: 0
|
||||||
|
});
|
||||||
|
model.set('_availablePosts', new Backbone.Collection([{}, {}])); // 2 posts
|
||||||
|
model.trigger('loadMorePosts');
|
||||||
|
expect(model.get('offset')).to.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers loading and loaded events for more posts', function () {
|
||||||
|
var stub = sinon.stub(CommunicationComponent, 'getPosts', function() {
|
||||||
|
var deferred = jQuery.Deferred();
|
||||||
|
deferred.resolve([{}]); // 1 post
|
||||||
|
return deferred;
|
||||||
|
});
|
||||||
|
var spy = sinon.spy(model, 'trigger');
|
||||||
|
|
||||||
|
model.set({
|
||||||
|
amount: 2,
|
||||||
|
offset: 0
|
||||||
|
});
|
||||||
|
model.set('_availablePosts', new Backbone.Collection([{}, {}])); // 2 posts
|
||||||
|
model._loadMorePosts();
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
spy.restore();
|
||||||
|
|
||||||
|
expect(spy.withArgs('loadingMorePosts').calledOnce).to.be.true;
|
||||||
|
expect(spy.withArgs('morePostsLoaded').calledOnce).to.be.true;
|
||||||
|
expect(model.get('_availablePosts').length).to.equal(3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('block view', function () {
|
describe('block view', function () {
|
||||||
|
@@ -1073,7 +1073,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
posts: {
|
posts: {
|
||||||
amount: '8',
|
amount: '10',
|
||||||
contentType: 'post', // 'post'|'page'|'mailpoet_page'
|
contentType: 'post', // 'post'|'page'|'mailpoet_page'
|
||||||
postStatus: 'publish', // 'draft'|'pending'|'private'|'publish'|'future'
|
postStatus: 'publish', // 'draft'|'pending'|'private'|'publish'|'future'
|
||||||
inclusionType: 'include', // 'include'|'exclude'
|
inclusionType: 'include', // 'include'|'exclude'
|
||||||
|
@@ -23,3 +23,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mailpoet_post_selection_container">
|
<div class="mailpoet_post_selection_container">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mailpoet_post_selection_loading" style="visibility: hidden;">
|
||||||
|
<%= __('Loading posts...') %>
|
||||||
|
</div>
|
||||||
|
Reference in New Issue
Block a user