diff --git a/public/src/client/category.js b/public/src/client/category.js index 3aff45420e..b14a80d0c9 100644 --- a/public/src/client/category.js +++ b/public/src/client/category.js @@ -89,28 +89,22 @@ define('forum/category', [ } function handleLoadMoreSubcategories() { - $('[component="category/load-more-subcategories"]').on('click', function () { + $('[component="category/load-more-subcategories"]').on('click', async function () { const btn = $(this); - socket.emit('categories.loadMoreSubCategories', { - cid: ajaxify.data.cid, - start: ajaxify.data.nextSubCategoryStart, - }, function (err, data) { - if (err) { - return alerts.error(err); - } - btn.toggleClass('hidden', !data.length || data.length < ajaxify.data.subCategoriesPerPage); - if (!data.length) { - return; - } - app.parseAndTranslate('category', 'children', { children: data }, function (html) { - html.find('.timeago').timeago(); - $('[component="category/subcategory/container"]').append(html); - ajaxify.data.nextSubCategoryStart += ajaxify.data.subCategoriesPerPage; - ajaxify.data.subCategoriesLeft -= data.length; - btn.toggleClass('hidden', ajaxify.data.subCategoriesLeft <= 0) - .translateText('[[category:x-more-categories, ' + ajaxify.data.subCategoriesLeft + ']]'); - }); + const { categories: data } = await api.get(`/categories/${ajaxify.data.cid}/children?start=${ajaxify.data.nextSubCategoryStart}`); + btn.toggleClass('hidden', !data.length || data.length < ajaxify.data.subCategoriesPerPage); + if (!data.length) { + return; + } + app.parseAndTranslate('category', 'children', { children: data }, function (html) { + html.find('.timeago').timeago(); + $('[component="category/subcategory/container"]').append(html); + ajaxify.data.nextSubCategoryStart += ajaxify.data.subCategoriesPerPage; + ajaxify.data.subCategoriesLeft -= data.length; + btn.toggleClass('hidden', ajaxify.data.subCategoriesLeft <= 0) + .translateText('[[category:x-more-categories, ' + ajaxify.data.subCategoriesLeft + ']]'); }); + return false; }); } diff --git a/src/api/categories.js b/src/api/categories.js index 442131b4fd..7cb7a17f69 100644 --- a/src/api/categories.js +++ b/src/api/categories.js @@ -85,6 +85,27 @@ categoriesAPI.getTopicCount = async (caller, { cid }) => { categoriesAPI.getPosts = async (caller, { cid }) => await categories.getRecentReplies(cid, caller.uid, 0, 4); +categoriesAPI.getChildren = async (caller, { cid, start }) => { + if (!start || start < 0) { + start = 0; + } + start = parseInt(start, 10); + + const allowed = await privileges.categories.can('read', cid, caller.uid); + if (!allowed) { + throw new Error('[[error:no-privileges]]'); + } + + const category = await categories.getCategoryData(cid); + await categories.getChildrenTree(category, caller.uid); + const allCategories = []; + categories.flattenCategories(allCategories, category.children); + await categories.getRecentTopicReplies(allCategories, caller.uid); + + const payload = category.children.slice(start, start + category.subCategoriesPerPage); + return { categories: payload }; +}; + categoriesAPI.setWatchState = async (caller, { cid, state, uid }) => { let targetUid = caller.uid; const cids = Array.isArray(cid) ? cid.map(cid => parseInt(cid, 10)) : [parseInt(cid, 10)]; diff --git a/src/controllers/write/categories.js b/src/controllers/write/categories.js index e987b433ce..e068f06305 100644 --- a/src/controllers/write/categories.js +++ b/src/controllers/write/categories.js @@ -45,6 +45,12 @@ Categories.getPosts = async (req, res) => { helpers.formatApiResponse(200, res, posts); }; +Categories.getChildren = async (req, res) => { + const { cid } = req.params; + const { start } = req.query; + helpers.formatApiResponse(200, res, await api.categories.getChildren(req, { cid, start })); +}; + Categories.setWatchState = async (req, res) => { const { cid } = req.params; let { uid, state } = req.body; diff --git a/src/routes/write/categories.js b/src/routes/write/categories.js index f1e2f39504..9121ee9a7f 100644 --- a/src/routes/write/categories.js +++ b/src/routes/write/categories.js @@ -16,8 +16,9 @@ module.exports = function () { setupApiRoute(router, 'put', '/:cid', [...middlewares], controllers.write.categories.update); setupApiRoute(router, 'delete', '/:cid', [...middlewares], controllers.write.categories.delete); - setupApiRoute(router, 'get', '/:cid/count', [...middlewares], controllers.write.categories.getTopicCount); - setupApiRoute(router, 'get', '/:cid/posts', [...middlewares], controllers.write.categories.getPosts); + setupApiRoute(router, 'get', '/:cid/count', [...middlewares, middleware.assert.category], controllers.write.categories.getTopicCount); + setupApiRoute(router, 'get', '/:cid/posts', [...middlewares, middleware.assert.category], controllers.write.categories.getPosts); + setupApiRoute(router, 'get', '/:cid/children', [...middlewares, middleware.assert.category], controllers.write.categories.getChildren); setupApiRoute(router, 'put', '/:cid/watch', [...middlewares, middleware.assert.category], controllers.write.categories.setWatchState); setupApiRoute(router, 'delete', '/:cid/watch', [...middlewares, middleware.assert.category], controllers.write.categories.setWatchState); diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index e2b647f71a..a62d55edfe 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -167,20 +167,14 @@ SocketCategories.isModerator = async function (socket, cid) { }; SocketCategories.loadMoreSubCategories = async function (socket, data) { + sockets.warnDeprecated(socket, `GET /api/v3/categories/:cid/children`); + 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); + + const { categories: children } = await api.categories.getChildren(socket, data); + return children; }; require('../promisify')(SocketCategories);