added a new section that only shows unread topics, added mark all read button, closes #140

v1.18.x
Baris Soner Usakli 12 years ago
parent 811d2df728
commit 78f462e1e6

@ -751,6 +751,10 @@ body .navbar .nodebb-inline-block {
}
}
#mark-allread-btn {
margin-bottom:15px;
}
@-webkit-keyframes scroll-2 /* Safari and Chrome */
{
0% {top: 0px;}

@ -44,7 +44,13 @@
socket.on('event:new_post', function(data) {
++newPostCount;
updateAlertText();
});
$('#mark-allread-btn').on('click', function() {
socket.emit('api:topics.markAllRead');
$(this).remove();
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
});
})();

@ -27,6 +27,7 @@
"users/[^]*": "account",
"recent": "recent",
"unread": "unread",
"popular": "category",
"active": "category"
},

@ -49,10 +49,10 @@
<li>
<a href="/recent">Recent <!--<span class="badge badge-inverse">3</span>--></a>
</li>
<!--<li>
<a href="/popular">Popular</a>
</li>
<li>
<a href="/unread">Unread</a>
</li>
<!--<li>
<a href="/active">Active</a>
</li>-->
<li>

@ -15,8 +15,6 @@
<strong>There are no recent topics.</strong>
</div>
<button class="btn">Mark All Read</button><br/><br/>
<div class="category row">
<div class="{topic_row_size}">
<ul id="topics-container">

@ -0,0 +1,54 @@
<div class="container">
<ul class="breadcrumb">
<li><a href="/">Home</a><span class="divider">/</span></li>
<li class="active">{category_name}</li>
<div id="category_active_users"></div>
</ul>
</div>
<a href="/unread">
<div class="alert hide" id="new-topics-alert"></div>
</a>
<div class="alert alert-warning {no_topics_message}" id="category-no-topics">
<strong>There are no unread topics.</strong>
</div>
<div>
<button id="mark-allread-btn" class="btn {show_markallread_button}">Mark All Read</button>
</div>
<div class="category row">
<div class="{topic_row_size}">
<ul id="topics-container">
<!-- BEGIN topics -->
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
<li class="category-item {topics.deleted-class}">
<div class="row-fluid">
<div class="span12 topic-row img-polaroid">
<div class="latest-post visible-desktop">
<div class="pull-right">
<img style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
<p><strong>{topics.teaser_username}</strong>: {topics.teaser_text}</p>
<span>posted {topics.teaser_timestamp} ago</span>
</div>
</div>
<div>
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
<small>
<strong><i class="{topics.pin-icon}"></i><i class="{topics.lock-icon}"></i></strong>
Posted {topics.relativeTime} ago by
<strong>{topics.username}</strong>.
</small>
</div>
</div>
</div>
</li>
</a>
<!-- END topics -->
</ul>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/recent.js"></script>

@ -307,7 +307,7 @@ var RDB = require('./redis.js'),
feed.updateTopic(tid, cid);
RDB.zadd('categories:recent_posts:cid:' + cid, Date.now(), pid);
RDB.zadd('categories:recent_posts:cid:' + cid, timestamp, pid);
// this is a bit of a naive implementation, defn something to look at post-MVP
RDB.scard('cid:' + cid + ':active_users', function(amount) {
@ -319,7 +319,7 @@ var RDB = require('./redis.js'),
});
});
user.onNewPostMade(uid, tid, pid, timestamp);
user.onNewPostMade(uid, tid, pid, timestamp);
var imgur = require('./imgur');
// move clientID to config

@ -14,7 +14,6 @@
return {
/* sets */
tid: 'topics:tid',
read_by_uid: 'tid:' + tid + ':read_by_uid',
/* sorted sets */

@ -94,8 +94,6 @@ marked.setOptions({
var timestamp = Date.now();
RDB.zremrangebyscore('topics:recent', '-inf', timestamp - 86400000);
RDB.zrevrangebyscore([ 'topics:recent', '+inf', timestamp - 86400000], function(err, tids) {
var latestTopics = {
@ -120,11 +118,60 @@ marked.setOptions({
});
});
}
Topics.getUnreadTopics = function(uid, start, stop, callback) {
var unreadTopics = {
'category_name' : 'Unread',
'show_sidebar' : 'hidden',
'show_topic_button' : 'hidden',
'show_markallread_button': 'show',
'no_topics_message' : 'hidden',
'topic_row_size': 'span12',
'topics' : []
};
RDB.zrevrange('topics:recent', start, stop, function (err, tids) {
function noUnreadTopics() {
unreadTopics.no_topics_message = 'show';
unreadTopics.show_markallread_button = 'hidden';
callback(unreadTopics);
}
if (!tids || !tids.length) {
noUnreadTopics();
return;
}
Topics.hasReadTopics(tids, uid, function(read) {
var unreadTids = tids.filter(function(tid, index, self) {
return read[index] === 0;
});
if (!unreadTids || !unreadTids.length) {
noUnreadTopics();
return;
}
Topics.getTopicsByTids(unreadTids, uid, function(topicData) {
unreadTopics.topics = topicData;
callback(unreadTopics);
});
});
});
}
Topics.getTopicsByTids = function(tids, current_user, callback, category_id) {
var retrieved_topics = [];
if(!Array.isArray(tids) || tids.length === 0) {
callback(retrieved_topics);
return;
}
function getTopicInfo(topicData, callback) {
function getUserName(next) {
@ -134,20 +181,20 @@ marked.setOptions({
}
function hasReadTopic(next) {
topics.hasReadTopic(topicData.tid, current_user, function(hasRead) {
Topics.hasReadTopic(topicData.tid, current_user, function(hasRead) {
next(null, hasRead);
});
}
function getTeaserInfo(next) {
topics.getTeaser(topicData.tid, function(err, teaser) {
Topics.getTeaser(topicData.tid, function(err, teaser) {
next(null, teaser || {});
});
}
// temporary. I don't think this call should belong here
function getPrivileges(next) {
Categories.privileges(category_id, current_user, function(user_privs) {
categories.privileges(category_id, current_user, function(user_privs) {
next(null, user_privs);
});
}
@ -173,7 +220,7 @@ marked.setOptions({
}
function loadTopic(tid, callback) {
topics.getTopicData(tid, function(topicData) {
Topics.getTopicData(tid, function(topicData) {
if(!topicData) {
return callback(null);
}
@ -354,10 +401,11 @@ marked.setOptions({
});
}
Topics.markAllRead = function(uid) {
Topics.markAllRead = function(uid, callback) {
RDB.smembers('topics:tid', function(err, tids) {
if(err) {
console.log(err);
callback(err, null);
return;
}
@ -366,6 +414,8 @@ marked.setOptions({
Topics.markAsRead(tids[i], uid);
}
}
callback(null, true);
});
}
@ -513,7 +563,7 @@ marked.setOptions({
// Global Topics
if (uid == null) uid = 0;
if (uid !== null) {
RDB.sadd(schema.topics().tid, tid);
RDB.sadd('topics:tid', tid);
} else {
// need to add some unique key sent by client so we can update this with the real uid later
RDB.lpush(schema.topics().queued_tids, tid);

@ -150,7 +150,7 @@ var express = require('express'),
// Basic Routes (entirely client-side parsed, goal is to move the rest of the crap in this file into this one section)
(function() {
var routes = ['login', 'register', 'account', 'recent', 'popular', 'active', '403', '404'];
var routes = ['login', 'register', 'account', 'recent', 'unread', 'popular', 'active', '403', '404'];
for (var i=0, ii=routes.length; i<ii; i++) {
(function(route) {
@ -388,6 +388,16 @@ var express = require('express'),
}
});
app.get('/test', function(req, res) {
topics.getUnreadTopics(4, 0, 9, function(data) {
console.log('ll', data.topics.length);
topics.getUnreadTopics(4, data.topics.length, data.topics.length + 9, function(data2) {
var finalData = [data,data2];
res.json(finalData);
});
});
});
});
// These functions are called via ajax once the initial page is loaded to populate templates with data
@ -482,19 +492,24 @@ var express = require('express'),
}, req.params.id, uid);
break;
case 'recent' :
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
break;
case 'unread':
topics.getUnreadTopics(uid, 0, -1, function(data) {
res.json(data);
});
break;
case 'popular' :
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
break;
case 'active' :
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
topics.getLatestTopics(uid, 0, 9, function(data) {
res.json(data);
});
break;
case 'confirm':
user.email.confirm(req.params.id, function(data) {

@ -337,6 +337,19 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
socket.on('api:topics.post', function(data) {
topics.post(socket, uid, data.title, data.content, data.category_id, data.images);
});
socket.on('api:topics.markAllRead', function(data) {
topics.markAllRead(uid, function(err, success) {
if(!err && success) {
socket.emit('event:alert', {
title: 'Success',
message: 'All topics marked as read!',
type: 'success',
timeout: 2000
});
}
});
});
socket.on('api:posts.reply', function(data) {
posts.reply(socket, data.topic_id, uid, data.content, data.images);

Loading…
Cancel
Save