mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 03:55:55 +01:00
closes #6005
This commit is contained in:
@@ -10,5 +10,6 @@
|
|||||||
"all-topics": "All Topics",
|
"all-topics": "All Topics",
|
||||||
"new-topics": "New Topics",
|
"new-topics": "New Topics",
|
||||||
"watched-topics": "Watched Topics",
|
"watched-topics": "Watched Topics",
|
||||||
"unreplied-topics": "Unreplied Topics"
|
"unreplied-topics": "Unreplied Topics",
|
||||||
|
"multiple-categories-selected": "Multiple Selected"
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,8 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit
|
|||||||
|
|
||||||
Recent.watchForNewPosts();
|
Recent.watchForNewPosts();
|
||||||
|
|
||||||
|
Recent.handleCategorySelection();
|
||||||
|
|
||||||
$('#new-topics-alert').on('click', function () {
|
$('#new-topics-alert').on('click', function () {
|
||||||
$(this).addClass('hide');
|
$(this).addClass('hide');
|
||||||
});
|
});
|
||||||
@@ -38,7 +40,7 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onNewTopic(data) {
|
function onNewTopic(data) {
|
||||||
if (ajaxify.data.selectedCategory && parseInt(ajaxify.data.selectedCategory.cid, 10) !== parseInt(data.cid, 10)) {
|
if (ajaxify.data.selectedCids && ajaxify.data.selectedCids.indexOf(parseInt(data.cid, 10)) === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ajaxify.data.selectedCategory && parseInt(ajaxify.data.selectedCategory.cid, 10) !== parseInt(post.topic.cid, 10)) {
|
if (ajaxify.data.selectedCids && ajaxify.data.selectedCids.indexOf(parseInt(post.topic.cid, 10)) === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +89,56 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit
|
|||||||
showAlert();
|
showAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Recent.handleCategorySelection = function () {
|
||||||
|
function getSelectedCids() {
|
||||||
|
var cids = [];
|
||||||
|
$('[component="category/list"] [data-cid]').each(function (index, el) {
|
||||||
|
if ($(el).find('i.fa-check').length) {
|
||||||
|
cids.push(parseInt($(el).attr('data-cid'), 10));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cids.sort(function (a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
|
return cids;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('[component="category/dropdown"]').on('hidden.bs.dropdown', function () {
|
||||||
|
var cids = getSelectedCids();
|
||||||
|
var changed = ajaxify.data.selectedCids.length !== cids.length;
|
||||||
|
ajaxify.data.selectedCids.forEach(function (cid, index) {
|
||||||
|
if (cid !== cids[index]) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
var url = ajaxify.data.selectedFilter.url;
|
||||||
|
if (cids.length) {
|
||||||
|
url += '?' + decodeURIComponent($.param({ cid: cids }));
|
||||||
|
}
|
||||||
|
ajaxify.go(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('[component="category/list"]').on('click', '[data-cid]', function (ev) {
|
||||||
|
function selectChildren(parentCid, flag) {
|
||||||
|
$('[component="category/list"] [data-parent-cid="' + parentCid + '"] [component="category/select/icon"]').toggleClass('fa-check', flag);
|
||||||
|
$('[component="category/list"] [data-parent-cid="' + parentCid + '"]').each(function (index, el) {
|
||||||
|
selectChildren($(el).attr('data-cid'), flag);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var categoryEl = $(this);
|
||||||
|
var cid = $(this).attr('data-cid');
|
||||||
|
if (ev.ctrlKey) {
|
||||||
|
selectChildren(cid, !categoryEl.find('[component="category/select/icon"]').hasClass('fa-check'));
|
||||||
|
}
|
||||||
|
categoryEl.find('[component="category/select/icon"]').toggleClass('fa-check');
|
||||||
|
$('[component="category/list"] li').first().find('i').toggleClass('fa-check', !getSelectedCids().length);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Recent.removeListeners = function () {
|
Recent.removeListeners = function () {
|
||||||
socket.removeListener('event:new_topic', onNewTopic);
|
socket.removeListener('event:new_topic', onNewTopic);
|
||||||
socket.removeListener('event:new_post', onNewPost);
|
socket.removeListener('event:new_post', onNewPost);
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', '
|
|||||||
|
|
||||||
recent.watchForNewPosts();
|
recent.watchForNewPosts();
|
||||||
|
|
||||||
|
recent.handleCategorySelection();
|
||||||
|
|
||||||
$(window).trigger('action:topics.loaded', { topics: ajaxify.data.topics });
|
$(window).trigger('action:topics.loaded', { topics: ajaxify.data.topics });
|
||||||
|
|
||||||
$('#markSelectedRead').on('click', function () {
|
$('#markSelectedRead').on('click', function () {
|
||||||
@@ -88,12 +90,11 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', '
|
|||||||
if (direction < 0 || !$('[component="category"]').length) {
|
if (direction < 0 || !$('[component="category"]').length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var params = utils.params();
|
|
||||||
var cid = params.cid;
|
|
||||||
infinitescroll.loadMore('topics.loadMoreUnreadTopics', {
|
infinitescroll.loadMore('topics.loadMoreUnreadTopics', {
|
||||||
after: $('[component="category"]').attr('data-nextstart'),
|
after: $('[component="category"]').attr('data-nextstart'),
|
||||||
count: config.topicsPerPage,
|
count: config.topicsPerPage,
|
||||||
cid: cid,
|
cid: utils.params().cid,
|
||||||
filter: ajaxify.data.selectedFilter.filter,
|
filter: ajaxify.data.selectedFilter.filter,
|
||||||
}, function (data, done) {
|
}, function (data, done) {
|
||||||
if (data.topics && data.topics.length) {
|
if (data.topics && data.topics.length) {
|
||||||
|
|||||||
@@ -91,11 +91,8 @@ module.exports = function (Categories) {
|
|||||||
db.getSortedSetsMembers(keys, next);
|
db.getSortedSetsMembers(keys, next);
|
||||||
},
|
},
|
||||||
function (results, next) {
|
function (results, next) {
|
||||||
var tids = _.flatten(results);
|
var tids = _.uniq(_.flatten(results).filter(Boolean));
|
||||||
|
|
||||||
tids = tids.filter(function (tid, index, array) {
|
|
||||||
return !!tid && array.indexOf(tid) === index;
|
|
||||||
});
|
|
||||||
privileges.topics.filterTids('read', tids, uid, next);
|
privileges.topics.filterTids('read', tids, uid, next);
|
||||||
},
|
},
|
||||||
function (tids, next) {
|
function (tids, next) {
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ helpers.buildTitle = function (pageTitle) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
helpers.getWatchedCategories = function (uid, selectedCid, callback) {
|
helpers.getWatchedCategories = function (uid, selectedCid, callback) {
|
||||||
|
if (selectedCid && !Array.isArray(selectedCid)) {
|
||||||
|
selectedCid = [selectedCid];
|
||||||
|
}
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
user.getWatchedCategories(uid, next);
|
user.getWatchedCategories(uid, next);
|
||||||
@@ -193,14 +196,30 @@ helpers.getWatchedCategories = function (uid, selectedCid, callback) {
|
|||||||
categoryData = categoryData.filter(function (category) {
|
categoryData = categoryData.filter(function (category) {
|
||||||
return category && !category.link;
|
return category && !category.link;
|
||||||
});
|
});
|
||||||
|
var selectedCategory = [];
|
||||||
var selectedCategory;
|
var selectedCids = [];
|
||||||
categoryData.forEach(function (category) {
|
categoryData.forEach(function (category) {
|
||||||
category.selected = parseInt(category.cid, 10) === parseInt(selectedCid, 10);
|
category.selected = selectedCid ? selectedCid.indexOf(String(category.cid)) !== -1 : false;
|
||||||
if (category.selected) {
|
if (category.selected) {
|
||||||
selectedCategory = category;
|
selectedCategory.push(category);
|
||||||
|
selectedCids.push(parseInt(category.cid, 10));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
selectedCids.sort(function (a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedCategory.length > 1) {
|
||||||
|
selectedCategory = {
|
||||||
|
icon: 'fa-plus',
|
||||||
|
name: '[[unread:multiple-categories-selected]]',
|
||||||
|
bgColor: '#ddd',
|
||||||
|
};
|
||||||
|
} else if (selectedCategory.length === 1) {
|
||||||
|
selectedCategory = selectedCategory[0];
|
||||||
|
} else {
|
||||||
|
selectedCategory = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
var categoriesData = [];
|
var categoriesData = [];
|
||||||
var tree = categories.getTree(categoryData, 0);
|
var tree = categories.getTree(categoryData, 0);
|
||||||
@@ -209,7 +228,7 @@ helpers.getWatchedCategories = function (uid, selectedCid, callback) {
|
|||||||
recursive(category, categoriesData, '');
|
recursive(category, categoriesData, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
next(null, { categories: categoriesData, selectedCategory: selectedCategory });
|
next(null, { categories: categoriesData, selectedCategory: selectedCategory, selectedCids: selectedCids });
|
||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var validator = require('validator');
|
var querystring = require('querystring');
|
||||||
|
|
||||||
var user = require('../user');
|
var user = require('../user');
|
||||||
var topics = require('../topics');
|
var topics = require('../topics');
|
||||||
@@ -53,6 +53,7 @@ recentController.get = function (req, res, next) {
|
|||||||
function (data) {
|
function (data) {
|
||||||
data.categories = categoryData.categories;
|
data.categories = categoryData.categories;
|
||||||
data.selectedCategory = categoryData.selectedCategory;
|
data.selectedCategory = categoryData.selectedCategory;
|
||||||
|
data.selectedCids = categoryData.selectedCids;
|
||||||
data.nextStart = stop + 1;
|
data.nextStart = stop + 1;
|
||||||
data.set = 'topics:recent';
|
data.set = 'topics:recent';
|
||||||
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
|
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
|
||||||
@@ -74,7 +75,8 @@ recentController.get = function (req, res, next) {
|
|||||||
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[recent:title]]' }]);
|
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[recent:title]]' }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.querystring = cid ? ('?cid=' + validator.escape(String(cid))) : '';
|
data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : '';
|
||||||
|
|
||||||
res.render('recent', data);
|
res.render('recent', data);
|
||||||
},
|
},
|
||||||
], next);
|
], next);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var querystring = require('querystring');
|
var querystring = require('querystring');
|
||||||
var validator = require('validator');
|
|
||||||
|
|
||||||
var pagination = require('../pagination');
|
var pagination = require('../pagination');
|
||||||
var user = require('../user');
|
var user = require('../user');
|
||||||
@@ -64,6 +63,7 @@ unreadController.get = function (req, res, next) {
|
|||||||
|
|
||||||
data.categories = results.watchedCategories.categories;
|
data.categories = results.watchedCategories.categories;
|
||||||
data.selectedCategory = results.watchedCategories.selectedCategory;
|
data.selectedCategory = results.watchedCategories.selectedCategory;
|
||||||
|
data.selectedCids = results.watchedCategories.selectedCids;
|
||||||
|
|
||||||
if (req.path.startsWith('/api/unread') || req.path.startsWith('/unread')) {
|
if (req.path.startsWith('/api/unread') || req.path.startsWith('/unread')) {
|
||||||
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]);
|
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]);
|
||||||
@@ -76,8 +76,7 @@ unreadController.get = function (req, res, next) {
|
|||||||
return filter && filter.selected;
|
return filter && filter.selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
data.querystring = cid ? ('?cid=' + validator.escape(String(cid))) : '';
|
data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : '';
|
||||||
|
|
||||||
res.render('unread', data);
|
res.render('unread', data);
|
||||||
},
|
},
|
||||||
], next);
|
], next);
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var privileges = require('../privileges');
|
var privileges = require('../privileges');
|
||||||
var user = require('../user');
|
var user = require('../user');
|
||||||
var categories = require('../categories');
|
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
|
|
||||||
module.exports = function (Topics) {
|
module.exports = function (Topics) {
|
||||||
@@ -23,22 +23,15 @@ module.exports = function (Topics) {
|
|||||||
nextStart: 0,
|
nextStart: 0,
|
||||||
topics: [],
|
topics: [],
|
||||||
};
|
};
|
||||||
|
if (cid && !Array.isArray(cid)) {
|
||||||
|
cid = [cid];
|
||||||
|
}
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
if (cid) {
|
db.getSortedSetRevRange('topics:recent', 0, 199, next);
|
||||||
categories.getTopicIds({
|
|
||||||
cid: cid,
|
|
||||||
start: 0,
|
|
||||||
stop: 199,
|
|
||||||
sort: 'newest_to_oldest',
|
|
||||||
}, next);
|
|
||||||
} else {
|
|
||||||
db.getSortedSetRevRange('topics:recent', 0, 199, next);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
function (tids, next) {
|
function (tids, next) {
|
||||||
filterTids(tids, uid, filter, next);
|
filterTids(tids, uid, filter, cid, next);
|
||||||
},
|
},
|
||||||
function (tids, next) {
|
function (tids, next) {
|
||||||
recentTopics.topicCount = tids.length;
|
recentTopics.topicCount = tids.length;
|
||||||
@@ -53,8 +46,7 @@ module.exports = function (Topics) {
|
|||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function filterTids(tids, uid, filter, cid, callback) {
|
||||||
function filterTids(tids, uid, filter, callback) {
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
if (filter === 'watched') {
|
if (filter === 'watched') {
|
||||||
@@ -84,9 +76,10 @@ module.exports = function (Topics) {
|
|||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
function (results, next) {
|
function (results, next) {
|
||||||
|
cid = cid && cid.map(String);
|
||||||
tids = results.topicData.filter(function (topic) {
|
tids = results.topicData.filter(function (topic) {
|
||||||
if (topic && topic.cid) {
|
if (topic && topic.cid) {
|
||||||
return results.ignoredCids.indexOf(topic.cid.toString()) === -1;
|
return results.ignoredCids.indexOf(topic.cid.toString()) === -1 && (!cid || (cid.length && cid.indexOf(topic.cid.toString()) !== -1));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).map(function (topic) {
|
}).map(function (topic) {
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ module.exports = function (Topics) {
|
|||||||
|
|
||||||
var cutoff = params.cutoff || Topics.unreadCutoff();
|
var cutoff = params.cutoff || Topics.unreadCutoff();
|
||||||
|
|
||||||
|
if (params.cid && !Array.isArray(params.cid)) {
|
||||||
|
params.cid = [params.cid];
|
||||||
|
}
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
@@ -181,10 +185,11 @@ module.exports = function (Topics) {
|
|||||||
},
|
},
|
||||||
function (results, next) {
|
function (results, next) {
|
||||||
var topics = results.topics;
|
var topics = results.topics;
|
||||||
|
cid = cid && cid.map(String);
|
||||||
tids = topics.filter(function (topic, index) {
|
tids = topics.filter(function (topic, index) {
|
||||||
return topic && topic.cid &&
|
return topic && topic.cid &&
|
||||||
(!!results.isTopicsFollowed[index] || results.ignoredCids.indexOf(topic.cid.toString()) === -1) &&
|
(!!results.isTopicsFollowed[index] || results.ignoredCids.indexOf(topic.cid.toString()) === -1) &&
|
||||||
(!cid || parseInt(cid, 10) === parseInt(topic.cid, 10));
|
(!cid || (cid.length && cid.indexOf(String(topic.cid)) !== -1));
|
||||||
}).map(function (topic) {
|
}).map(function (topic) {
|
||||||
return topic.tid;
|
return topic.tid;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1133,7 +1133,7 @@ describe('Topic\'s', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should mark all read', function (done) {
|
it('should mark category topics read', function (done) {
|
||||||
socketTopics.markUnread({ uid: adminUid }, tid, function (err) {
|
socketTopics.markUnread({ uid: adminUid }, tid, function (err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
socketTopics.markCategoryTopicsRead({ uid: adminUid }, topic.categoryId, function (err) {
|
socketTopics.markCategoryTopicsRead({ uid: adminUid }, topic.categoryId, function (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user