mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 10:01:40 -05:00
Massively simplified all the posts_lists using the paginatedSub.
This commit is contained in:
commit
0be912db24
14 changed files with 160 additions and 257 deletions
119
client/app.js
119
client/app.js
|
@ -56,101 +56,40 @@ STATUS_PENDING=1;
|
||||||
STATUS_APPROVED=2;
|
STATUS_APPROVED=2;
|
||||||
STATUS_REJECTED=3;
|
STATUS_REJECTED=3;
|
||||||
FIND_APPROVED={$or: [{status: {$exists : false}}, {status: STATUS_APPROVED}]};
|
FIND_APPROVED={$or: [{status: {$exists : false}}, {status: STATUS_APPROVED}]};
|
||||||
TOP_PAGE_PER_PAGE = 10;
|
|
||||||
NEW_PAGE_PER_PAGE = 10;
|
|
||||||
BEST_PAGE_PER_PAGE = 10;
|
|
||||||
PENDING_PAGE_PER_PAGE = 10;
|
|
||||||
DIGEST_PAGE_PER_PAGE = 5;
|
DIGEST_PAGE_PER_PAGE = 5;
|
||||||
|
|
||||||
// name <- the name of various session vars that will be set:
|
var postListSubscription = function(find, options, per_page) {
|
||||||
// - 'nameReady' <- is the subscription loading or ready?
|
var handle = paginatedSubscription(per_page, 'paginatedPosts', find, options);
|
||||||
// - 'nameLimit' <- how many of this type are we currently displaying?
|
handle.fetch = function() {
|
||||||
// options:
|
return limitDocuments(Posts.find(find, options), handle.loaded());
|
||||||
// - find <- how to find the items
|
}
|
||||||
// - sort <- how to sort them
|
return handle;
|
||||||
// - perPage <- how many to display per-page
|
|
||||||
// -
|
|
||||||
postsForSub = {};
|
|
||||||
setupPostSubscription = function(name, options) {
|
|
||||||
var readyName = name + 'Ready';
|
|
||||||
var limitName = name + 'Limit';
|
|
||||||
|
|
||||||
if (options.perPage && ! Session.get(limitName))
|
|
||||||
Session.set(limitName, options.perPage);
|
|
||||||
|
|
||||||
// setup the subscription
|
|
||||||
Meteor.autosubscribe(function() {
|
|
||||||
Session.set(readyName, false);
|
|
||||||
|
|
||||||
var findOptions = {
|
|
||||||
sort: options.sort,
|
|
||||||
limit: options.perPage && Session.get(limitName)
|
|
||||||
};
|
|
||||||
|
|
||||||
var find = _.isFunction(options.find) ? options.find() : options.find;
|
|
||||||
Meteor.subscribe('posts', find || {}, findOptions, name, function() {
|
|
||||||
Session.set('initialLoad', false);
|
|
||||||
Session.set(readyName, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// setup a function to find the relevant posts (+deal with mm's lack of limit)
|
|
||||||
postsForSub[name] = function() {
|
|
||||||
var find = _.isFunction(options.find) ? options.find() : options.find;
|
|
||||||
var orderedPosts = Posts.find(find || {}, {sort: options.sort});
|
|
||||||
if (options.perPage) {
|
|
||||||
return limitDocuments(orderedPosts, Session.get(limitName));
|
|
||||||
} else {
|
|
||||||
return orderedPosts;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(Session.get('selectedPostId')){
|
var topPostsHandle = postListSubscription(FIND_APPROVED, {sort: {score: -1}}, 10);
|
||||||
setupPostSubscription('singlePost', {
|
var newPostsHandle = postListSubscription(FIND_APPROVED, {sort: {submitted: -1}}, 10);
|
||||||
find: function() { return Session.get('selectedPostId'); }
|
var bestPostsHandle = postListSubscription(FIND_APPROVED, {sort: {baseScore: -1}}, 10);
|
||||||
});
|
var pendingPostsHandle = postListSubscription(
|
||||||
// }
|
{$or: [{status: STATUS_PENDING}, {status: STATUS_REJECTED}]},
|
||||||
|
{sort: {score: -1}},
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
setupPostSubscription('topPosts', {
|
// setupPostSubscription('digestPosts', {
|
||||||
find: FIND_APPROVED,
|
// find: function() {
|
||||||
sort: {score: -1},
|
// var mDate = moment(Session.get('currentDate'));
|
||||||
perPage: TOP_PAGE_PER_PAGE
|
// var find = {
|
||||||
});
|
// submitted: {
|
||||||
|
// $gte: mDate.startOf('day').valueOf(),
|
||||||
setupPostSubscription('newPosts', {
|
// $lt: mDate.endOf('day').valueOf()
|
||||||
find: FIND_APPROVED,
|
// }
|
||||||
sort: {submitted: -1},
|
// };
|
||||||
perPage: NEW_PAGE_PER_PAGE
|
// find=_.extend(find, FIND_APPROVED);
|
||||||
});
|
// return find;
|
||||||
|
// },
|
||||||
setupPostSubscription('bestPosts', {
|
// sort: {score: -1}
|
||||||
find: FIND_APPROVED,
|
// ,perPage: DIGEST_PAGE_PER_PAGE
|
||||||
sort: {baseScore: -1},
|
// });
|
||||||
perPage: NEW_PAGE_PER_PAGE
|
|
||||||
});
|
|
||||||
|
|
||||||
setupPostSubscription('pendingPosts', {
|
|
||||||
find: {$or: [{status: STATUS_PENDING}, {status: STATUS_REJECTED}]},
|
|
||||||
sort: {score: -1},
|
|
||||||
perPage: PENDING_PAGE_PER_PAGE
|
|
||||||
});
|
|
||||||
|
|
||||||
setupPostSubscription('digestPosts', {
|
|
||||||
find: function() {
|
|
||||||
var mDate = moment(Session.get('currentDate'));
|
|
||||||
var find = {
|
|
||||||
submitted: {
|
|
||||||
$gte: mDate.startOf('day').valueOf(),
|
|
||||||
$lt: mDate.endOf('day').valueOf()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
find=_.extend(find, FIND_APPROVED);
|
|
||||||
return find;
|
|
||||||
},
|
|
||||||
sort: {score: -1}
|
|
||||||
,perPage: DIGEST_PAGE_PER_PAGE
|
|
||||||
});
|
|
||||||
|
|
||||||
// ** Categories **
|
// ** Categories **
|
||||||
|
|
||||||
|
|
48
client/lib/paginated_sub.js
Normal file
48
client/lib/paginated_sub.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
PaginatedSubscriptionHandle = function(perPage) {
|
||||||
|
this.perPage = perPage;
|
||||||
|
this._limit = perPage;
|
||||||
|
this._limitListeners = new Meteor.deps._ContextSet();
|
||||||
|
this._loaded = 0;
|
||||||
|
this._loadedListeners = new Meteor.deps._ContextSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
PaginatedSubscriptionHandle.prototype.loaded = function() {
|
||||||
|
this._loadedListeners.addCurrentContext();
|
||||||
|
return this._loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaginatedSubscriptionHandle.prototype.limit = function() {
|
||||||
|
this._limitListeners.addCurrentContext();
|
||||||
|
return this._limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaginatedSubscriptionHandle.prototype.loading = function() {
|
||||||
|
return this.loaded() < this.limit();
|
||||||
|
}
|
||||||
|
|
||||||
|
PaginatedSubscriptionHandle.prototype.loadNextPage = function() {
|
||||||
|
this._limit += this.perPage;
|
||||||
|
this._limitListeners.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
PaginatedSubscriptionHandle.prototype.done = function() {
|
||||||
|
// XXX: check if subs that are canceled before they are ready ever fire ready?
|
||||||
|
// if they do we need to increase loaded by perPage, not set it to limit
|
||||||
|
this._loaded = this._limit;
|
||||||
|
this._loadedListeners.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
paginatedSubscription = function (perPage/*, name, arguments */) {
|
||||||
|
var handle = new PaginatedSubscriptionHandle(perPage);
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
|
||||||
|
Meteor.autosubscribe(function() {
|
||||||
|
var subHandle = Meteor.subscribe.apply(this, args.concat([
|
||||||
|
handle.limit(), function() { handle.done(); }
|
||||||
|
]));
|
||||||
|
handle.stop = subHandle.stop;
|
||||||
|
});
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
|
@ -1,20 +1,4 @@
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
// XXX: could we just work this out programmatically based on the name?
|
|
||||||
// -- fix this along with the general problem of subscription mess
|
|
||||||
PAGE_SUBS = {
|
|
||||||
'posts_top': 'topPostsReady',
|
|
||||||
'posts_new': 'newPostsReady',
|
|
||||||
'posts_best': 'bestPostsReady',
|
|
||||||
'posts_pending': 'pendingPostsReady',
|
|
||||||
'posts_digest': 'digestPostsReady',
|
|
||||||
'post_page': 'singlePostReady',
|
|
||||||
'post_edit': 'singlePostReady',
|
|
||||||
'comment_page': 'commentReady',
|
|
||||||
'comment_reply': 'commentReady',
|
|
||||||
'comment_edit': 'commentReady'
|
|
||||||
}
|
|
||||||
|
|
||||||
// specific router functions
|
// specific router functions
|
||||||
digest = function(year, month, day, view){
|
digest = function(year, month, day, view){
|
||||||
var destination = (typeof view === 'undefined') ? 'posts_digest' : 'posts_digest_'+view
|
var destination = (typeof view === 'undefined') ? 'posts_digest' : 'posts_digest_'+view
|
||||||
|
@ -191,10 +175,6 @@
|
||||||
return isAdmin(Meteor.user()) ? page : "no_rights";
|
return isAdmin(Meteor.user()) ? page : "no_rights";
|
||||||
},
|
},
|
||||||
|
|
||||||
awaitSubscription: function(page) {
|
|
||||||
return Session.equals(PAGE_SUBS[page], true) ? page : 'loading';
|
|
||||||
},
|
|
||||||
|
|
||||||
// if the user is logged in but their profile isn't filled out enough
|
// if the user is logged in but their profile isn't filled out enough
|
||||||
requireProfile: function(page) {
|
requireProfile: function(page) {
|
||||||
var user = Meteor.user();
|
var user = Meteor.user();
|
||||||
|
@ -220,7 +200,6 @@
|
||||||
});
|
});
|
||||||
//
|
//
|
||||||
Meteor.Router.filter('requireProfile');
|
Meteor.Router.filter('requireProfile');
|
||||||
Meteor.Router.filter('awaitSubscription', {only: ['posts_top', 'posts_new', 'posts_pending', 'posts_best']});
|
|
||||||
Meteor.Router.filter('requireLogin', {only: ['comment_reply','post_submit']});
|
Meteor.Router.filter('requireLogin', {only: ['comment_reply','post_submit']});
|
||||||
Meteor.Router.filter('canView', {only: ['posts_top', 'posts_new', 'posts_digest', 'posts_best']});
|
Meteor.Router.filter('canView', {only: ['posts_top', 'posts_new', 'posts_digest', 'posts_best']});
|
||||||
Meteor.Router.filter('isLoggedOut', {only: ['user_signin', 'user_signup']});
|
Meteor.Router.filter('isLoggedOut', {only: ['user_signin', 'user_signup']});
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<template name="posts_best">
|
|
||||||
<div class="posts grid list">
|
|
||||||
{{#each posts}}
|
|
||||||
{{> post_item}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div class="grid more-button {{#if allPostsLoaded}} hidden {{/if}}">
|
|
||||||
<a class="more-link" href="#">Load more</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,27 +0,0 @@
|
||||||
Template.posts_best.posts = function() {
|
|
||||||
return postsForSub.bestPosts();
|
|
||||||
};
|
|
||||||
|
|
||||||
Template.posts_best.helpers({
|
|
||||||
allPostsLoaded: function(){
|
|
||||||
return postsForSub.bestPosts().length < Session.get('bestPostsLimit');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.posts_best.rendered = function(){
|
|
||||||
var distanceFromTop = 0;
|
|
||||||
$('.post').each(function(){
|
|
||||||
distanceFromTop += $(this).height();
|
|
||||||
});
|
|
||||||
$('body').css('min-height',distanceFromTop+160);
|
|
||||||
$('.more-button').css('top', distanceFromTop+"px");
|
|
||||||
}
|
|
||||||
|
|
||||||
Template.posts_best.events({
|
|
||||||
'click .more-link': function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
Session.set('currentScroll',$('body').scrollTop());
|
|
||||||
Session.set('bestPostsLimit', Session.get('bestPostsLimit') + BEST_PAGE_PER_PAGE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
32
client/views/posts/posts_list.html
Normal file
32
client/views/posts/posts_list.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<template name="posts_list">
|
||||||
|
<div class="posts grid list">
|
||||||
|
{{#each posts}}
|
||||||
|
{{> post_item}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{#if postsReady}}
|
||||||
|
<div class="grid more-button {{#if allPostsLoaded}} hidden {{/if}}">
|
||||||
|
<a class="more-link" href="#">Load more</a>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div>SPINNER...</div>
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- and the various pages that use the above template -->
|
||||||
|
<!-- XXX: makes me want to be able to set a context from the router... -->
|
||||||
|
<template name="posts_top">
|
||||||
|
{{> posts_list topPostsHandle}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="posts_new">
|
||||||
|
{{> posts_list newPostsHandle}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="posts_best">
|
||||||
|
{{> posts_list bestPostsHandle}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="posts_pending">
|
||||||
|
{{> posts_list pendingPostsHandle}}
|
||||||
|
</template>
|
42
client/views/posts/posts_list.js
Normal file
42
client/views/posts/posts_list.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
Template.posts_top.topPostsHandle = function() {
|
||||||
|
return topPostsHandle;
|
||||||
|
}
|
||||||
|
Template.posts_new.newPostsHandle = function() {
|
||||||
|
return newPostsHandle;
|
||||||
|
}
|
||||||
|
Template.posts_best.bestPostsHandle = function() {
|
||||||
|
return bestPostsHandle;
|
||||||
|
}
|
||||||
|
Template.posts_best.pendingPostsHandle = function() {
|
||||||
|
return pendingPostsHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Template.posts_list.helpers({
|
||||||
|
posts: function() {
|
||||||
|
return this.fetch();
|
||||||
|
},
|
||||||
|
postsReady: function() {
|
||||||
|
return ! this.loading();
|
||||||
|
},
|
||||||
|
allPostsLoaded: function(){
|
||||||
|
return this.fetch().length < this.loaded()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.posts_top.rendered = function(){
|
||||||
|
var distanceFromTop = 0;
|
||||||
|
$('.post').each(function(){
|
||||||
|
distanceFromTop += $(this).height();
|
||||||
|
});
|
||||||
|
$('body').css('min-height',distanceFromTop+160);
|
||||||
|
$('.more-button').css('top', distanceFromTop+"px");
|
||||||
|
}
|
||||||
|
|
||||||
|
Template.posts_top.events({
|
||||||
|
'click .more-link': function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Session.set('currentScroll',$('body').scrollTop());
|
||||||
|
this.loadNextPage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<template name="posts_new">
|
|
||||||
<div class="posts grid list">
|
|
||||||
{{#each posts}}
|
|
||||||
{{> post_item}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div class="grid more-button {{#if allPostsLoaded}} hidden {{/if}}">
|
|
||||||
<a class="more-link" href="#">Load more</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,26 +0,0 @@
|
||||||
Template.posts_new.posts = function() {
|
|
||||||
return postsForSub.newPosts();
|
|
||||||
};
|
|
||||||
|
|
||||||
Template.posts_new.helpers({
|
|
||||||
allPostsLoaded: function(){
|
|
||||||
return postsForSub.newPosts().length < Session.get('newPostsLimit');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.posts_new.rendered = function(){
|
|
||||||
var distanceFromTop = 0;
|
|
||||||
$('.post').each(function(){
|
|
||||||
distanceFromTop += $(this).height();
|
|
||||||
});
|
|
||||||
$('body').css('min-height',distanceFromTop+160);
|
|
||||||
$('.more-button').css('top', distanceFromTop+"px");
|
|
||||||
}
|
|
||||||
|
|
||||||
Template.posts_new.events({
|
|
||||||
'click .more-link': function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
Session.set('currentScroll',$('body').scrollTop());
|
|
||||||
Session.set('newPostsLimit', Session.get('newPostsLimit') + NEW_PAGE_PER_PAGE)
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
<template name="posts_pending">
|
|
||||||
<div class="posts grid list">
|
|
||||||
{{#each posts}}
|
|
||||||
{{> post_item}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div class="grid more-button {{#if allPostsLoaded}} hidden {{/if}}">
|
|
||||||
<a class="more-link" href="#">Load more</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,25 +0,0 @@
|
||||||
Template.posts_pending.posts = function() {
|
|
||||||
return postsForSub.pendingPosts();
|
|
||||||
};
|
|
||||||
|
|
||||||
Template.posts_pending.helpers({
|
|
||||||
allPostsLoaded: function(){
|
|
||||||
return postsForSub.pendingPosts().length < Session.get('pendingPostsLimit');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.posts_pending.rendered = function(){
|
|
||||||
var distanceFromTop = 0;
|
|
||||||
$('.post').each(function(){
|
|
||||||
distanceFromTop += $(this).height();
|
|
||||||
});
|
|
||||||
$('.more-button').css('top', distanceFromTop+"px");
|
|
||||||
}
|
|
||||||
|
|
||||||
Template.posts_pending.events({
|
|
||||||
'click .more-link': function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
Session.set('currentScroll',$('body').scrollTop());
|
|
||||||
Session.set('pendingPostsLimit', Session.get('pendingPostsLimit') + NEW_PAGE_PER_PAGE)
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
<template name="posts_top">
|
|
||||||
<div class="posts grid list">
|
|
||||||
{{#each posts}}
|
|
||||||
{{> post_item}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div class="grid more-button {{#if allPostsLoaded}} hidden {{/if}}">
|
|
||||||
<a class="more-link" href="#">Load more</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,27 +0,0 @@
|
||||||
Template.posts_top.posts = function() {
|
|
||||||
return postsForSub.topPosts();
|
|
||||||
};
|
|
||||||
|
|
||||||
Template.posts_top.helpers({
|
|
||||||
allPostsLoaded: function(){
|
|
||||||
return postsForSub.topPosts().length < Session.get('topPostsLimit');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.posts_top.rendered = function(){
|
|
||||||
var distanceFromTop = 0;
|
|
||||||
$('.post').each(function(){
|
|
||||||
distanceFromTop += $(this).height();
|
|
||||||
});
|
|
||||||
$('body').css('min-height',distanceFromTop+160);
|
|
||||||
$('.more-button').css('top', distanceFromTop+"px");
|
|
||||||
}
|
|
||||||
|
|
||||||
Template.posts_top.events({
|
|
||||||
'click .more-link': function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
Session.set('currentScroll',$('body').scrollTop());
|
|
||||||
Session.set('topPostsLimit', Session.get('topPostsLimit') + TOP_PAGE_PER_PAGE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -54,6 +54,14 @@ Posts = new Meteor.Collection('posts');
|
||||||
// return Posts.find({}, {sort: {score: -1}});
|
// return Posts.find({}, {sort: {score: -1}});
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
Meteor.publish('paginatedPosts', function(find, options, limit) {
|
||||||
|
options = options || {};
|
||||||
|
options.limit = limit;
|
||||||
|
|
||||||
|
return Posts.find(find || {}, options);
|
||||||
|
});
|
||||||
|
|
||||||
Meteor.publish('posts', function(find, options, subName) {
|
Meteor.publish('posts', function(find, options, subName) {
|
||||||
var collection=Posts.find(find, options);
|
var collection=Posts.find(find, options);
|
||||||
var collectionArray=collection.fetch();
|
var collectionArray=collection.fetch();
|
||||||
|
|
Loading…
Add table
Reference in a new issue