mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 20:16:04 +01:00
added a new section that only shows unread topics, added mark all read button, closes #140
This commit is contained in:
@@ -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">
|
||||
|
||||
54
public/templates/unread.tpl
Normal file
54
public/templates/unread.tpl
Normal file
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user