mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	closes #6005
This commit is contained in:
		| @@ -10,5 +10,6 @@ | ||||
| 	"all-topics": "All Topics", | ||||
| 	"new-topics": "New 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.handleCategorySelection(); | ||||
|  | ||||
| 		$('#new-topics-alert').on('click', function () { | ||||
| 			$(this).addClass('hide'); | ||||
| 		}); | ||||
| @@ -38,7 +40,7 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit | ||||
| 	}; | ||||
|  | ||||
| 	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; | ||||
| 		} | ||||
|  | ||||
| @@ -64,7 +66,7 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit | ||||
| 			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; | ||||
| 		} | ||||
|  | ||||
| @@ -87,6 +89,56 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function (infinit | ||||
| 		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 () { | ||||
| 		socket.removeListener('event:new_topic', onNewTopic); | ||||
| 		socket.removeListener('event:new_post', onNewPost); | ||||
|   | ||||
| @@ -19,6 +19,8 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', ' | ||||
|  | ||||
| 		recent.watchForNewPosts(); | ||||
|  | ||||
| 		recent.handleCategorySelection(); | ||||
|  | ||||
| 		$(window).trigger('action:topics.loaded', { topics: ajaxify.data.topics }); | ||||
|  | ||||
| 		$('#markSelectedRead').on('click', function () { | ||||
| @@ -88,12 +90,11 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', ' | ||||
| 			if (direction < 0 || !$('[component="category"]').length) { | ||||
| 				return; | ||||
| 			} | ||||
| 			var params = utils.params(); | ||||
| 			var cid = params.cid; | ||||
|  | ||||
| 			infinitescroll.loadMore('topics.loadMoreUnreadTopics', { | ||||
| 				after: $('[component="category"]').attr('data-nextstart'), | ||||
| 				count: config.topicsPerPage, | ||||
| 				cid: cid, | ||||
| 				cid: utils.params().cid, | ||||
| 				filter: ajaxify.data.selectedFilter.filter, | ||||
| 			}, function (data, done) { | ||||
| 				if (data.topics && data.topics.length) { | ||||
|   | ||||
| @@ -91,11 +91,8 @@ module.exports = function (Categories) { | ||||
| 				db.getSortedSetsMembers(keys, 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); | ||||
| 			}, | ||||
| 			function (tids, next) { | ||||
|   | ||||
| @@ -179,6 +179,9 @@ helpers.buildTitle = function (pageTitle) { | ||||
| }; | ||||
|  | ||||
| helpers.getWatchedCategories = function (uid, selectedCid, callback) { | ||||
| 	if (selectedCid && !Array.isArray(selectedCid)) { | ||||
| 		selectedCid = [selectedCid]; | ||||
| 	} | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			user.getWatchedCategories(uid, next); | ||||
| @@ -193,14 +196,30 @@ helpers.getWatchedCategories = function (uid, selectedCid, callback) { | ||||
| 			categoryData = categoryData.filter(function (category) { | ||||
| 				return category && !category.link; | ||||
| 			}); | ||||
|  | ||||
| 			var selectedCategory; | ||||
| 			var selectedCategory = []; | ||||
| 			var selectedCids = []; | ||||
| 			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) { | ||||
| 					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 tree = categories.getTree(categoryData, 0); | ||||
| @@ -209,7 +228,7 @@ helpers.getWatchedCategories = function (uid, selectedCid, callback) { | ||||
| 				recursive(category, categoriesData, ''); | ||||
| 			}); | ||||
|  | ||||
| 			next(null, { categories: categoriesData, selectedCategory: selectedCategory }); | ||||
| 			next(null, { categories: categoriesData, selectedCategory: selectedCategory, selectedCids: selectedCids }); | ||||
| 		}, | ||||
| 	], callback); | ||||
| }; | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|  | ||||
| var async = require('async'); | ||||
| var nconf = require('nconf'); | ||||
| var validator = require('validator'); | ||||
| var querystring = require('querystring'); | ||||
|  | ||||
| var user = require('../user'); | ||||
| var topics = require('../topics'); | ||||
| @@ -53,6 +53,7 @@ recentController.get = function (req, res, next) { | ||||
| 		function (data) { | ||||
| 			data.categories = categoryData.categories; | ||||
| 			data.selectedCategory = categoryData.selectedCategory; | ||||
| 			data.selectedCids = categoryData.selectedCids; | ||||
| 			data.nextStart = stop + 1; | ||||
| 			data.set = 'topics:recent'; | ||||
| 			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.querystring = cid ? ('?cid=' + validator.escape(String(cid))) : ''; | ||||
| 			data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : ''; | ||||
|  | ||||
| 			res.render('recent', data); | ||||
| 		}, | ||||
| 	], next); | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
|  | ||||
| var async = require('async'); | ||||
| var querystring = require('querystring'); | ||||
| var validator = require('validator'); | ||||
|  | ||||
| var pagination = require('../pagination'); | ||||
| var user = require('../user'); | ||||
| @@ -64,6 +63,7 @@ unreadController.get = function (req, res, next) { | ||||
|  | ||||
| 			data.categories = results.watchedCategories.categories; | ||||
| 			data.selectedCategory = results.watchedCategories.selectedCategory; | ||||
| 			data.selectedCids = results.watchedCategories.selectedCids; | ||||
|  | ||||
| 			if (req.path.startsWith('/api/unread') || req.path.startsWith('/unread')) { | ||||
| 				data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]); | ||||
| @@ -76,8 +76,7 @@ unreadController.get = function (req, res, next) { | ||||
| 				return filter && filter.selected; | ||||
| 			}); | ||||
|  | ||||
| 			data.querystring = cid ? ('?cid=' + validator.escape(String(cid))) : ''; | ||||
|  | ||||
| 			data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : ''; | ||||
| 			res.render('unread', data); | ||||
| 		}, | ||||
| 	], next); | ||||
|   | ||||
| @@ -3,11 +3,11 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| var async = require('async'); | ||||
|  | ||||
| var db = require('../database'); | ||||
| var plugins = require('../plugins'); | ||||
| var privileges = require('../privileges'); | ||||
| var user = require('../user'); | ||||
| var categories = require('../categories'); | ||||
| var meta = require('../meta'); | ||||
|  | ||||
| module.exports = function (Topics) { | ||||
| @@ -23,22 +23,15 @@ module.exports = function (Topics) { | ||||
| 			nextStart: 0, | ||||
| 			topics: [], | ||||
| 		}; | ||||
|  | ||||
| 		if (cid && !Array.isArray(cid)) { | ||||
| 			cid = [cid]; | ||||
| 		} | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				if (cid) { | ||||
| 					categories.getTopicIds({ | ||||
| 						cid: cid, | ||||
| 						start: 0, | ||||
| 						stop: 199, | ||||
| 						sort: 'newest_to_oldest', | ||||
| 					}, next); | ||||
| 				} else { | ||||
| 					db.getSortedSetRevRange('topics:recent', 0, 199, next); | ||||
| 				} | ||||
| 				db.getSortedSetRevRange('topics:recent', 0, 199, next); | ||||
| 			}, | ||||
| 			function (tids, next) { | ||||
| 				filterTids(tids, uid, filter, next); | ||||
| 				filterTids(tids, uid, filter, cid, next); | ||||
| 			}, | ||||
| 			function (tids, next) { | ||||
| 				recentTopics.topicCount = tids.length; | ||||
| @@ -53,8 +46,7 @@ module.exports = function (Topics) { | ||||
| 		], callback); | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| 	function filterTids(tids, uid, filter, callback) { | ||||
| 	function filterTids(tids, uid, filter, cid, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				if (filter === 'watched') { | ||||
| @@ -84,9 +76,10 @@ module.exports = function (Topics) { | ||||
| 				}, next); | ||||
| 			}, | ||||
| 			function (results, next) { | ||||
| 				cid = cid && cid.map(String); | ||||
| 				tids = results.topicData.filter(function (topic) { | ||||
| 					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; | ||||
| 				}).map(function (topic) { | ||||
|   | ||||
| @@ -75,6 +75,10 @@ module.exports = function (Topics) { | ||||
|  | ||||
| 		var cutoff = params.cutoff || Topics.unreadCutoff(); | ||||
|  | ||||
| 		if (params.cid && !Array.isArray(params.cid)) { | ||||
| 			params.cid = [params.cid]; | ||||
| 		} | ||||
|  | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				async.parallel({ | ||||
| @@ -181,10 +185,11 @@ module.exports = function (Topics) { | ||||
| 			}, | ||||
| 			function (results, next) { | ||||
| 				var topics = results.topics; | ||||
| 				cid = cid && cid.map(String); | ||||
| 				tids = topics.filter(function (topic, index) { | ||||
| 					return topic && topic.cid && | ||||
| 						(!!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) { | ||||
| 					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) { | ||||
| 				assert.ifError(err); | ||||
| 				socketTopics.markCategoryTopicsRead({ uid: adminUid }, topic.categoryId, function (err) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user