Files
NodeBB/src/socket.io/categories.js

176 lines
5.5 KiB
JavaScript
Raw Normal View History

'use strict';
2019-09-13 23:34:52 -04:00
const categories = require('../categories');
const privileges = require('../privileges');
const user = require('../user');
const topics = require('../topics');
const api = require('../api');
const sockets = require('.');
2019-09-13 23:34:52 -04:00
const SocketCategories = module.exports;
2015-12-28 10:42:15 +02:00
Categories refactor (#9257) * feat: wip categories pagination * feat: add subCategoriesPerPage setting * feat: add load more sub categories button to category page * fix: openapi spec * feat: show sub categories left on category page hide button when no more categories left * breaking: rename categories to allCategories on /search categories contains the search results * fix: spec * refactor: remove cidsPerPage * fix: tests * feat: use component for subcategories * fix: prevent negative subCategoriesLeft * feat: new category filter/search WIP * feat: remove categories from /tag * fix: dont load all categories when showing move modal * feat: allow adding custom categories to list * breaking: dont load entire category tree on post queue removed unused code add hooks to filter/selector add options to filter/selector * feat: make selector modal work again * feat: replace old search module * fix: topic move selector * feat: dont load all categories on create category modal * fix: fix more categorySelectors * feat: dont load entire category tree on group details page * feat: dont load all categories on home page and user settings page * feat: add pagination to /user/:userslug/categories * fix: update schemas * fix: more tests * fix: test * feat: flags page, dont return entire category tree * fix: flag test * feat: categories manage page dont load all categories allow changing root category clear caches properly * fix: spec * feat: admins&mods page dont load all categories * fix: spec * fix: dont load all children when opening dropdown * fix: on search results dont return all children * refactor: pass all options, rename options.cids to options.selectedCids * fix: #9266 * fix: index 0 * fix: spec * feat: #9265, add setObjectBulk * refactor: shoter updateOrder * feat: selectors on categories/category * fix: tests and search filter * fix: category update test * feat: pagination on acp categories page show order in set order modal * fix: allow drag&drop on pages > 1 in /admin/manage/categories * fix: teasers for deep nested categories fix sub category display on /category page * fix: spec * refactor: use eslint-disable-next-line * refactor: shorter
2021-02-07 15:09:52 -05:00
require('./categories/search')(SocketCategories);
2019-09-13 23:34:52 -04:00
SocketCategories.getRecentReplies = async function (socket, cid) {
return await categories.getRecentReplies(cid, socket.uid, 4);
};
2019-09-13 23:34:52 -04:00
SocketCategories.get = async function (socket) {
async function getCategories() {
const cids = await categories.getCidsByPrivilege('categories:cid', socket.uid, 'find');
return await categories.getCategoriesData(cids);
}
const [isAdmin, categoriesData] = await Promise.all([
user.isAdministrator(socket.uid),
getCategories(),
]);
return categoriesData.filter(category => category && (!category.disabled || isAdmin));
};
2019-09-13 23:34:52 -04:00
SocketCategories.getWatchedCategories = async function (socket) {
const [categoriesData, ignoredCids] = await Promise.all([
categories.getCategoriesByPrivilege('cid:0:children', socket.uid, 'find'),
user.getIgnoredCategories(socket.uid),
]);
return categoriesData.filter(category => category && !ignoredCids.includes(String(category.cid)));
2015-05-26 15:05:46 -04:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.loadMore = async function (socket, data) {
2015-01-08 13:47:15 -05:00
if (!data) {
2019-09-13 23:34:52 -04:00
throw new Error('[[error:invalid-data]]');
2014-01-17 12:49:21 -05:00
}
data.query = data.query || {};
2019-09-13 23:34:52 -04:00
const [userPrivileges, settings, targetUid] = await Promise.all([
privileges.categories.get(data.cid, socket.uid),
user.getSettings(socket.uid),
user.getUidByUserslug(data.query.author),
]);
if (!userPrivileges.read) {
throw new Error('[[error:no-privileges]]');
}
const infScrollTopicsPerPage = 20;
const sort = data.sort || data.categoryTopicSort;
let start = Math.max(0, parseInt(data.after, 10));
if (data.direction === -1) {
start -= infScrollTopicsPerPage;
}
let stop = start + infScrollTopicsPerPage - 1;
start = Math.max(0, start);
stop = Math.max(0, stop);
const result = await categories.getCategoryTopics({
uid: socket.uid,
cid: data.cid,
start: start,
stop: stop,
sort: sort,
settings: settings,
query: data.query,
tag: data.query.tag,
targetUid: targetUid,
});
categories.modifyTopicsByPrivilege(result.topics, userPrivileges);
2019-09-13 23:34:52 -04:00
result.privileges = userPrivileges;
result.template = {
category: true,
name: 'category',
};
return result;
};
2019-09-13 23:34:52 -04:00
SocketCategories.getTopicCount = async function (socket, cid) {
return await categories.getCategoryField(cid, 'topic_count');
2014-04-04 12:42:41 -04:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.getCategoriesByPrivilege = async function (socket, privilege) {
return await categories.getCategoriesByPrivilege('categories:cid', socket.uid, privilege);
2014-08-15 15:45:01 -04:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.getMoveCategories = async function (socket, data) {
return await SocketCategories.getSelectCategories(socket, data);
};
2019-09-13 23:34:52 -04:00
SocketCategories.getSelectCategories = async function (socket) {
const [isAdmin, categoriesData] = await Promise.all([
user.isAdministrator(socket.uid),
2019-09-20 22:10:08 -04:00
categories.buildForSelect(socket.uid, 'find', ['disabled', 'link']),
2019-09-13 23:34:52 -04:00
]);
return categoriesData.filter(category => category && (!category.disabled || isAdmin) && !category.link);
2015-12-28 10:42:15 +02:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.setWatchState = async function (socket, data) {
if (!data || !data.cid || !data.state) {
2019-09-13 23:34:52 -04:00
throw new Error('[[error:invalid-data]]');
}
2021-02-04 00:01:39 -07:00
return await ignoreOrWatch(async (uid, cids) => {
await user.setCategoryWatchState(uid, cids, categories.watchStates[data.state]);
2019-09-13 23:34:52 -04:00
}, socket, data);
};
2019-09-13 23:34:52 -04:00
SocketCategories.watch = async function (socket, data) {
2019-09-25 21:24:07 -04:00
return await ignoreOrWatch(user.watchCategory, socket, data);
2014-08-29 15:57:20 -04:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.ignore = async function (socket, data) {
2019-09-25 21:24:07 -04:00
return await ignoreOrWatch(user.ignoreCategory, socket, data);
2014-08-29 15:57:20 -04:00
};
2019-09-13 23:34:52 -04:00
async function ignoreOrWatch(fn, socket, data) {
let targetUid = socket.uid;
const cids = Array.isArray(data.cid) ? data.cid.map(cid => parseInt(cid, 10)) : [parseInt(data.cid, 10)];
if (data.hasOwnProperty('uid')) {
targetUid = data.uid;
}
2019-09-13 23:34:52 -04:00
await user.isAdminOrGlobalModOrSelf(socket.uid, targetUid);
const allCids = await categories.getAllCidsFromSet('categories:cid');
const categoryData = await categories.getCategoriesFields(allCids, ['cid', 'parentCid']);
// filter to subcategories of cid
let cat;
do {
cat = categoryData.find(c => !cids.includes(c.cid) && cids.includes(c.parentCid));
if (cat) {
cids.push(cat.cid);
}
} while (cat);
await fn(targetUid, cids);
2019-09-13 23:34:52 -04:00
await topics.pushUnreadCount(targetUid);
return cids;
2016-08-22 17:16:52 -05:00
}
2019-09-13 23:34:52 -04:00
SocketCategories.isModerator = async function (socket, cid) {
return await user.isModerator(socket.uid, cid);
2015-03-18 17:50:47 -04:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.getCategory = async function (socket, cid) {
Categories refactor (#9257) * feat: wip categories pagination * feat: add subCategoriesPerPage setting * feat: add load more sub categories button to category page * fix: openapi spec * feat: show sub categories left on category page hide button when no more categories left * breaking: rename categories to allCategories on /search categories contains the search results * fix: spec * refactor: remove cidsPerPage * fix: tests * feat: use component for subcategories * fix: prevent negative subCategoriesLeft * feat: new category filter/search WIP * feat: remove categories from /tag * fix: dont load all categories when showing move modal * feat: allow adding custom categories to list * breaking: dont load entire category tree on post queue removed unused code add hooks to filter/selector add options to filter/selector * feat: make selector modal work again * feat: replace old search module * fix: topic move selector * feat: dont load all categories on create category modal * fix: fix more categorySelectors * feat: dont load entire category tree on group details page * feat: dont load all categories on home page and user settings page * feat: add pagination to /user/:userslug/categories * fix: update schemas * fix: more tests * fix: test * feat: flags page, dont return entire category tree * fix: flag test * feat: categories manage page dont load all categories allow changing root category clear caches properly * fix: spec * feat: admins&mods page dont load all categories * fix: spec * fix: dont load all children when opening dropdown * fix: on search results dont return all children * refactor: pass all options, rename options.cids to options.selectedCids * fix: #9266 * fix: index 0 * fix: spec * feat: #9265, add setObjectBulk * refactor: shoter updateOrder * feat: selectors on categories/category * fix: tests and search filter * fix: category update test * feat: pagination on acp categories page show order in set order modal * fix: allow drag&drop on pages > 1 in /admin/manage/categories * fix: teasers for deep nested categories fix sub category display on /category page * fix: spec * refactor: use eslint-disable-next-line * refactor: shorter
2021-02-07 15:09:52 -05:00
sockets.warnDeprecated(socket, 'GET /api/v3/categories/:cid');
return await api.categories.get(socket, { cid });
// return await apiController.getCategoryData(cid, socket.uid);
2016-03-08 11:24:32 +02:00
};
2019-09-13 23:34:52 -04:00
SocketCategories.loadMoreSubCategories = async function (socket, data) {
if (!data || !data.cid || !(parseInt(data.start, 10) > 0)) {
throw new Error('[[error:invalid-data]]');
}
const allowed = await privileges.categories.can('read', data.cid, socket.uid);
if (!allowed) {
throw new Error('[[error:no-privileges]]');
}
const category = await categories.getCategoryData(data.cid);
await categories.getChildrenTree(category, socket.uid);
const allCategories = [];
categories.flattenCategories(allCategories, category.children);
await categories.getRecentTopicReplies(allCategories, socket.uid);
const start = parseInt(data.start, 10);
return category.children.slice(start, start + category.subCategoriesPerPage);
};
2019-09-13 23:34:52 -04:00
require('../promisify')(SocketCategories);