diff --git a/README.md b/README.md
index 43f2b7cb29..7a2fc06c55 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@ It is important to ensure that your NodeBB and database servers are secured. Bea
## Upgrading NodeBB
-Detailed upgrade instructions are listed in [Upgrading NodeBB](https://docs.nodebb.org/en/latest/upgrading/index.html)
+Detailed upgrade instructions are listed in [Upgrading NodeBB](https://docs.nodebb.org/configuring/upgrade/)
## License
diff --git a/package.json b/package.json
index dcf8d58a27..40bfe8a776 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "nodebb",
"license": "GPL-3.0",
"description": "NodeBB Forum",
- "version": "1.5.1",
+ "version": "1.5.2",
"homepage": "http://www.nodebb.org",
"repository": {
"type": "git",
@@ -55,7 +55,7 @@
"morgan": "^1.3.2",
"mousetrap": "^1.5.3",
"nconf": "~0.8.2",
- "nodebb-plugin-composer-default": "5.0.1",
+ "nodebb-plugin-composer-default": "5.0.3",
"nodebb-plugin-dbsearch": "2.0.6",
"nodebb-plugin-emoji-extended": "1.1.1",
"nodebb-plugin-emoji-one": "1.2.1",
@@ -68,7 +68,7 @@
"nodebb-theme-persona": "5.0.13",
"nodebb-theme-slick": "1.1.0",
"nodebb-theme-vanilla": "6.0.10",
- "nodebb-widget-essentials": "3.0.0",
+ "nodebb-widget-essentials": "3.0.1",
"nodemailer": "2.6.4",
"nodemailer-sendmail-transport": "1.0.0",
"nodemailer-smtp-transport": "^2.4.1",
diff --git a/public/language/cs/search.json b/public/language/cs/search.json
index b4ae4ca7db..7500385c23 100644
--- a/public/language/cs/search.json
+++ b/public/language/cs/search.json
@@ -2,33 +2,33 @@
"results_matching": "%1 result(s) matching \"%2\", (%3 seconds)",
"no-matches": "No matches found",
"advanced-search": "Pokročilé hledání",
- "in": "In",
+ "in": "v",
"titles": "Titles",
"titles-posts": "Titles and Posts",
- "posted-by": "Posted by",
- "in-categories": "In Categories",
+ "posted-by": "Napsal",
+ "in-categories": "V kategoriích",
"search-child-categories": "Search child categories",
- "has-tags": "Has tags",
+ "has-tags": "Obsahuje značky",
"reply-count": "Reply Count",
- "at-least": "At least",
- "at-most": "At most",
+ "at-least": "Nejméně",
+ "at-most": "Nejvíce",
"relevance": "Relevance",
- "post-time": "Post time",
+ "post-time": "Čas příspěvku",
"newer-than": "Novější než",
"older-than": "Starší než",
- "any-date": "Any date",
+ "any-date": "Jakékoliv datum",
"yesterday": "Včera",
"one-week": "Jeden týden",
"two-weeks": "Dva týdny",
"one-month": "Jeden měsíc",
- "three-months": "Three months",
+ "three-months": "Tři měsíce",
"six-months": "Šest měsíců",
"one-year": "Jeden rok",
"sort-by": "Řadit dle",
"last-reply-time": "Čas poslední odpovědi",
- "topic-title": "Topic title",
+ "topic-title": "Název tématu",
"number-of-replies": "Počet odpovědí",
- "number-of-views": "Number of views",
+ "number-of-views": "Počet zobrazení",
"topic-start-date": "Topic start date",
"username": "Uživatelské jméno",
"category": "Kategorie",
diff --git a/public/language/cs/topic.json b/public/language/cs/topic.json
index 98429c8ad0..91d6e4d1aa 100644
--- a/public/language/cs/topic.json
+++ b/public/language/cs/topic.json
@@ -13,9 +13,9 @@
"notify_me": "Dostávat upozornění na nové odpovědi",
"quote": "Citovat",
"reply": "Odpovědět",
- "replies_to_this_post": "%1 Replies",
- "one_reply_to_this_post": "1 Reply",
- "last_reply_time": "Last reply",
+ "replies_to_this_post": "%1 odpovědí",
+ "one_reply_to_this_post": "1 odpověď",
+ "last_reply_time": "Poslední odpověď",
"reply-as-topic": "Odpovědět jako Téma",
"guest-login-reply": "Přihlásit se pro odpověď",
"edit": "Upravit",
@@ -28,8 +28,8 @@
"share": "Sdílet",
"tools": "Nástroje",
"locked": "Uzamčeno",
- "pinned": "Pinned",
- "moved": "Moved",
+ "pinned": "Připnuto",
+ "moved": "Přesunuto",
"bookmark_instructions": "Click here to return to the last read post in this thread.",
"flag_title": "Flag this post for moderation",
"deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.",
@@ -37,47 +37,47 @@
"not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.",
"ignoring_topic.message": "You will no longer see this topic in the unread topics list. You will be notified when you are mentioned or your post is up voted.",
"login_to_subscribe": "Please register or log in in order to subscribe to this topic.",
- "markAsUnreadForAll.success": "Topic marked as unread for all.",
+ "markAsUnreadForAll.success": "Téma označeno jako nepřečtené pro všechny.",
"mark_unread": "Označ za nepřečtené",
"mark_unread.success": "Téma označeno jako nepřečtené",
"watch": "Sledovat",
"unwatch": "Přesta sledovat",
- "watch.title": "Be notified of new replies in this topic",
+ "watch.title": "Být upozorněn u nových odpovědí v tomto tématu",
"unwatch.title": "Přestat sledovat toto téma",
"share_this_post": "Sdílet toto téma",
"watching": "Sledováno",
"not-watching": "Nesledováno",
- "ignoring": "Ignoring",
+ "ignoring": "Ignorování",
"watching.description": "Notify me of new replies.
Show topic in unread.",
"not-watching.description": "Do not notify me of new replies.
Show topic in unread if category is not ignored.",
"ignoring.description": "Do not notify me of new replies.
Do not show topic in unread.",
"thread_tools.title": "Správa tématu",
- "thread_tools.markAsUnreadForAll": "Mark unread for all",
+ "thread_tools.markAsUnreadForAll": "Označit jako nepřečtené pro všechny",
"thread_tools.pin": "Připnout téma",
"thread_tools.unpin": "Odepnout téma",
"thread_tools.lock": "Zamknout téma",
"thread_tools.unlock": "Odemknout téma",
"thread_tools.move": "Přesunout téma",
"thread_tools.move_all": "Přesunout vše",
- "thread_tools.select_category": "Select Category",
+ "thread_tools.select_category": "Vybrat kategorii",
"thread_tools.fork": "Větvit téma",
"thread_tools.delete": "Odstranit téma",
"thread_tools.delete-posts": "Odstranit přispěvky",
"thread_tools.delete_confirm": "Opravdu chcete smazat toto téma.",
"thread_tools.restore": "Obnovit téma",
- "thread_tools.restore_confirm": "Are you sure you want to restore this topic?",
- "thread_tools.purge": "Purge Topic",
- "thread_tools.purge_confirm": "Are you sure you want to purge this topic?",
- "topic_move_success": "This topic has been successfully moved to %1",
- "post_delete_confirm": "Are you sure you want to delete this post?",
- "post_restore_confirm": "Are you sure you want to restore this post?",
- "post_purge_confirm": "Are you sure you want to purge this post?",
+ "thread_tools.restore_confirm": "Jste si jist/a, že chcete obnovit toto téma?",
+ "thread_tools.purge": "Vyčistit téma",
+ "thread_tools.purge_confirm": "Jste si jist/a, že chcete vyčistit toto téma?",
+ "topic_move_success": "Toto téma bylo úspěšně přesunuto do %1",
+ "post_delete_confirm": "Jste si jist/a, že chcete odstranit tento příspěvek?",
+ "post_restore_confirm": "Jste si jist/a, že chcete obnovit tento příspěvek?",
+ "post_purge_confirm": "Jste si jist/a, že chcete tento příspěvek vyčistit?",
"load_categories": "Načítání kategorií",
"confirm_move": "Přesunout",
"confirm_fork": "Rozdělit",
- "bookmark": "Bookmark",
- "bookmarks": "Bookmarks",
- "bookmarks.has_no_bookmarks": "You haven't bookmarked any posts yet.",
+ "bookmark": "Záložka",
+ "bookmarks": "Záložky",
+ "bookmarks.has_no_bookmarks": "Ještě jste nezazáložkoval žádný příspěvek.",
"loading_more_posts": "Načítání více příspěvků",
"move_topic": "Přesunout téma",
"move_topics": "Přesunout témata",
@@ -86,9 +86,9 @@
"fork_topic": "Rozdělit příspěvek",
"fork_topic_instruction": "Vyber příspěvky, které chceš oddělit",
"fork_no_pids": "Žádné příspěvky nebyly vybrány!",
- "fork_pid_count": "%1 post(s) selected",
+ "fork_pid_count": "Vybráno %1 příspěvek/ů",
"fork_success": "Successfully forked topic! Click here to go to the forked topic.",
- "delete_posts_instruction": "Click the posts you want to delete/purge",
+ "delete_posts_instruction": "Klikněte na příspěvek, který chcete odstranit/vyčistit",
"composer.title_placeholder": "Zadejte název tématu…",
"composer.handle_placeholder": "Jméno",
"composer.discard": "Zrušit",
@@ -101,7 +101,7 @@
"composer.thumb_url_placeholder": "http://example.com/thumb.png",
"composer.thumb_file_label": "Nebo nahrajte soubor",
"composer.thumb_remove": "Vymazat pole",
- "composer.drag_and_drop_images": "Drag and Drop Images Here",
+ "composer.drag_and_drop_images": "Přesuňte sem myší obrázek",
"more_users_and_guests": "%1 more user(s) and %2 guest(s)",
"more_users": "%1 more user(s)",
"more_guests": "%1 more guest(s)",
diff --git a/public/language/cs/user.json b/public/language/cs/user.json
index 63560d8b42..bcd94715cf 100644
--- a/public/language/cs/user.json
+++ b/public/language/cs/user.json
@@ -6,7 +6,7 @@
"postcount": "Počet příspěvků",
"email": "E-mail",
"confirm_email": "Potvrdit e-mail",
- "account_info": "Account Info",
+ "account_info": "Informace o účtu",
"ban_account": "Zablokovat účet",
"ban_account_confirm": "Opravdu chcete zablokovat tohoto uživatele?",
"unban_account": "Odblokovat účet",
@@ -23,7 +23,7 @@
"profile": "Profil",
"profile_views": "Zobrazení profilu",
"reputation": "Reputace",
- "bookmarks": "Bookmarks",
+ "bookmarks": "Záložky",
"watched": "Sledován",
"followers": "Sledují ho",
"following": "Sleduje",
@@ -31,8 +31,8 @@
"signature": "Podpis",
"birthday": "Datum narození",
"chat": "Chat",
- "chat_with": "Continue chat with %1",
- "new_chat_with": "Start new chat with %1",
+ "chat_with": "Pokračovat v chatu s %1",
+ "new_chat_with": "Začít nový chat s %1",
"flag-profile": "Flag Profile",
"follow": "Sledovat",
"unfollow": "Nesledovat",
@@ -60,14 +60,14 @@
"username_taken_workaround": "Zvolené uživatelské jméno je již zabrané, takže jsme ho trochu upravili. Nyní jste znám jako %1",
"password_same_as_username": "Vaše heslo je stejné jako vaše přihlašovací jméno. Zvolte si prosím jiné heslo.",
"password_same_as_email": "Vaše heslo je stejné jako váš e-mail. Zvolte si prosím jiné heslo.",
- "weak_password": "Weak password.",
+ "weak_password": "Slabé heslo.",
"upload_picture": "Nahrát obrázek",
"upload_a_picture": "Nahrát obrázek",
"remove_uploaded_picture": "Odstranit nahraný obrázek",
"upload_cover_picture": "Náhrát titulní obrázek",
- "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?",
- "crop_picture": "Crop picture",
- "upload_cropped_picture": "Crop and upload",
+ "remove_cover_picture_confirm": "Jste si jist, že vyjmout obrázek coveru?",
+ "crop_picture": "Oříznout obrázek",
+ "upload_cropped_picture": "Oříznout a nahrát",
"settings": "Nastavení",
"show_email": "Zobrazovat můj e-mail v profilu",
"show_fullname": "Zobrazovat celé jméno",
@@ -78,35 +78,35 @@
"digest_daily": "Denně",
"digest_weekly": "Týdně",
"digest_monthly": "Měsíčně",
- "send_chat_notifications": "Send an email if a new chat message arrives and I am not online",
- "send_post_notifications": "Send an email when replies are made to topics I am subscribed to",
- "settings-require-reload": "Some setting changes require a reload. Click here to reload the page.",
+ "send_chat_notifications": "Odeslat e-mail, dorazí-li nová zpráva chatu a já nejsem připojen",
+ "send_post_notifications": "Zaslat e-mail, přibudou-li nové odpovědi k tématu, kde mám přihlášen odběr",
+ "settings-require-reload": "Některá nastavení vyžadují znovu načtení. Pro znovu načtení stránky, klikněte zde.",
"has_no_follower": "Tohoto uživatele nikdo nesleduje :(",
"follows_no_one": "Tento uživatel nikoho nesleduje :(",
- "has_no_posts": "This user hasn't posted anything yet.",
- "has_no_topics": "This user hasn't posted any topics yet.",
+ "has_no_posts": "Tento uživatel ještě nic nenapsal.",
+ "has_no_topics": "Tento uživatel ještě nenapsal žádné téma.",
"has_no_watched_topics": "Tento uživatel zatím nesleduje žádná témata.",
"has_no_upvoted_posts": "This user hasn't upvoted any posts yet.",
"has_no_downvoted_posts": "This user hasn't downvoted any posts yet.",
- "has_no_voted_posts": "This user has no voted posts",
+ "has_no_voted_posts": "Tento uživatel nemá žádné hlasovací příspěvky",
"email_hidden": "E-mail skryt",
"hidden": "skrytý",
- "paginate_description": "Paginate topics and posts instead of using infinite scroll",
+ "paginate_description": "Stránkovat témata a příspěvky místo použití nekonečného posunování",
"topics_per_page": "Témat na stránce",
"posts_per_page": "Příspěvků na stránce",
"notification_sounds": "Přehrát zvuk když dostanete notifikaci",
"notifications_and_sounds": "Upozornění a zvuky",
- "incoming-message-sound": "Incoming message sound",
- "outgoing-message-sound": "Outgoing message sound",
- "notification-sound": "Notification sound",
- "no-sound": "No sound",
+ "incoming-message-sound": "Zvuk příchozí zprávy",
+ "outgoing-message-sound": "Zvuk odchozí zprávy",
+ "notification-sound": "Zvuk oznámení",
+ "no-sound": "Bez zvuku",
"browsing": "Nastavení prohlížení",
- "open_links_in_new_tab": "Open outgoing links in new tab",
- "enable_topic_searching": "Enable In-Topic Searching",
+ "open_links_in_new_tab": "Otevřít odchozí odkaz v nové záložce",
+ "enable_topic_searching": "Povolit vyhledávání v tématu",
"topic_search_help": "If enabled, in-topic searching will override the browser's default page search behaviour and allow you to search through the entire topic, instead of what is only shown on screen",
- "delay_image_loading": "Delay Image Loading",
+ "delay_image_loading": "Zpoždění načtení obrázku",
"image_load_delay_help": "If enabled, images in topics will not load until they are scrolled into view",
- "scroll_to_my_post": "After posting a reply, show the new post",
+ "scroll_to_my_post": "Po odeslání odpovědi, zobrazit nový příspěvek",
"follow_topics_you_reply_to": "Sledovat témata, do kterých přispějete",
"follow_topics_you_create": "Sledovat témata, která vytvoříte",
"grouptitle": "Nadpis skupiny",
@@ -122,15 +122,15 @@
"sso.not-associated": "Click here to associate with",
"info.latest-flags": "Latest Flags",
"info.no-flags": "No Flagged Posts Found",
- "info.ban-history": "Recent Ban History",
- "info.no-ban-history": "This user has never been banned",
- "info.banned-until": "Banned until %1",
- "info.banned-permanently": "Banned permanently",
- "info.banned-reason-label": "Reason",
- "info.banned-no-reason": "No reason given.",
- "info.username-history": "Username History",
- "info.email-history": "Email History",
- "info.moderation-note": "Moderation Note",
- "info.moderation-note.success": "Moderation note saved",
- "info.moderation-note.add": "Add note"
+ "info.ban-history": "Poslední historie banování",
+ "info.no-ban-history": "Tento uživatel nebyl nikdy zabanován",
+ "info.banned-until": "Zabanován do %1",
+ "info.banned-permanently": "Permanentně zabanován",
+ "info.banned-reason-label": "Důvod",
+ "info.banned-no-reason": "Bez důvodu",
+ "info.username-history": "Historie uživatelského jména",
+ "info.email-history": "E-mailová historie",
+ "info.moderation-note": "Poznámka moderace",
+ "info.moderation-note.success": "Poznámka moderace byla uložena",
+ "info.moderation-note.add": "Přidat poznámku"
}
\ No newline at end of file
diff --git a/public/language/en-GB/admin/settings/uploads.json b/public/language/en-GB/admin/settings/uploads.json
index 35eaa5a58f..a458870354 100644
--- a/public/language/en-GB/admin/settings/uploads.json
+++ b/public/language/en-GB/admin/settings/uploads.json
@@ -5,7 +5,7 @@
"max-image-width": "Resize images down to specified width (in pixels)",
"max-image-width-help": "(in pixels, default: 760 pixels, set to 0 to disable)",
"max-file-size": "Maximum File Size (in KiB)",
- "max-file-size-help": "(in kilobytes, default: 2048 KiB)",
+ "max-file-size-help": "(in kibibytes, default: 2048 KiB)",
"allow-topic-thumbnails": "Allow users to upload topic thumbnails",
"topic-thumb-size": "Topic Thumb Size",
"allowed-file-extensions": "Allowed File Extensions",
@@ -18,9 +18,9 @@
"profile-image-dimension": "Profile Image Dimension",
"profile-image-dimension-help": "(in pixels, default: 128 pixels)",
"max-profile-image-size": "Maximum Profile Image File Size",
- "max-profile-image-size-help": "(in kilobytes, default: 256 KiB)",
+ "max-profile-image-size-help": "(in kibibytes, default: 256 KiB)",
"max-cover-image-size": "Maximum Cover Image File Size",
- "max-cover-image-size-help": "(in kilobytes, default: 2,048 KiB)",
+ "max-cover-image-size-help": "(in kibibytes, default: 2,048 KiB)",
"keep-all-user-images": "Keep old versions of avatars and profile covers on the server",
"profile-covers": "Profile Covers",
"default-covers": "Default Cover Images",
diff --git a/public/language/vi/admin/advanced/database.json b/public/language/vi/admin/advanced/database.json
index 27aaa79b67..29e08a3f7b 100644
--- a/public/language/vi/admin/advanced/database.json
+++ b/public/language/vi/admin/advanced/database.json
@@ -27,8 +27,8 @@
"redis.blocked-clients": "Người dùng vi phạm",
"redis.used-memory": "Bộ nhớ đã sử dụng",
"redis.memory-frag-ratio": "Memory Fragmentation Ratio",
- "redis.total-connections-recieved": "Total Connections Received",
- "redis.total-commands-processed": "Total Commands Processed",
+ "redis.total-connections-recieved": "Tổng số kết nối nhận được",
+ "redis.total-commands-processed": "Tổng số kết nối đã thực thi",
"redis.iops": "Instantaneous Ops. Per Second",
"redis.keyspace-hits": "Keyspace Hits",
"redis.keyspace-misses": "Keyspace Misses",
diff --git a/public/src/client/category.js b/public/src/client/category.js
index 6bf2ea0ffc..06af29ff3d 100644
--- a/public/src/client/category.js
+++ b/public/src/client/category.js
@@ -16,7 +16,7 @@ define('forum/category', [
var Category = {};
$(window).on('action:ajaxify.start', function (ev, data) {
- if (data.url && !data.url.startsWith('category/')) {
+ if (!String(data.url).startsWith('category/')) {
navigator.disable();
removeListeners();
diff --git a/public/src/client/topic.js b/public/src/client/topic.js
index 0a0d857663..57d276d986 100644
--- a/public/src/client/topic.js
+++ b/public/src/client/topic.js
@@ -23,7 +23,7 @@ define('forum/topic', [
Topic.replaceURLTimeout = 0;
}
- if (data.url && !data.url.startsWith('topic/')) {
+ if (!String(data.url).startsWith('topic/')) {
navigator.disable();
components.get('navbar/title').find('span').text('').hide();
app.removeAlert('bookmark');
diff --git a/public/src/client/topic/images.js b/public/src/client/topic/images.js
index 65ad386371..e121eda7c2 100644
--- a/public/src/client/topic/images.js
+++ b/public/src/client/topic/images.js
@@ -20,6 +20,7 @@ define('forum/topic/images', [
} else {
images.attr('data-state', 'loaded');
Images.wrapImagesInLinks(posts);
+ $(window).trigger('action:images.loaded');
}
};
@@ -75,6 +76,7 @@ define('forum/topic/images', [
adjusting = false;
Images.wrapImagesInLinks(posts);
+ $(window).trigger('action:images.loaded');
posts.length = 0;
}
}
diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js
index 38f7f0a087..193300dc0e 100644
--- a/src/categories/recentreplies.js
+++ b/src/categories/recentreplies.js
@@ -59,6 +59,25 @@ module.exports = function (Categories) {
], callback);
};
+ Categories.updateRecentTidForCid = function (cid, callback) {
+ async.waterfall([
+ function (next) {
+ db.getSortedSetRevRange('cid:' + cid + ':pids', 0, 0, next);
+ },
+ function (pid, next) {
+ pid = pid[0];
+ posts.getPostField(pid, 'tid', next);
+ },
+ function (tid, next) {
+ if (!parseInt(tid, 10)) {
+ return next();
+ }
+
+ Categories.updateRecentTid(cid, tid, next);
+ },
+ ], callback);
+ };
+
Categories.getRecentTopicReplies = function (categoryData, uid, callback) {
if (!Array.isArray(categoryData) || !categoryData.length) {
return callback();
@@ -180,8 +199,11 @@ module.exports = function (Categories) {
Categories.moveRecentReplies = function (tid, oldCid, cid, callback) {
callback = callback || function () {};
- updatePostCount(tid, oldCid, cid);
+
async.waterfall([
+ function (next) {
+ updatePostCount(tid, oldCid, cid, next);
+ },
function (next) {
topics.getPids(tid, next);
},
@@ -212,7 +234,6 @@ module.exports = function (Categories) {
};
function updatePostCount(tid, oldCid, newCid, callback) {
- callback = callback || function () {};
async.waterfall([
function (next) {
topics.getTopicField(tid, 'postcount', next);
@@ -228,7 +249,9 @@ module.exports = function (Categories) {
function (next) {
db.incrObjectFieldBy('category:' + newCid, 'post_count', postCount, next);
},
- ], next);
+ ], function (err) {
+ next(err);
+ });
},
], callback);
}
diff --git a/src/controllers/categories.js b/src/controllers/categories.js
index 9a17a47fc2..25e384c0ed 100644
--- a/src/controllers/categories.js
+++ b/src/controllers/categories.js
@@ -7,7 +7,7 @@ var categories = require('../categories');
var meta = require('../meta');
var helpers = require('./helpers');
-var categoriesController = {};
+var categoriesController = module.exports;
categoriesController.list = function (req, res, next) {
res.locals.metaTags = [{
@@ -34,32 +34,27 @@ categoriesController.list = function (req, res, next) {
categories.getRecentTopicReplies(allCategories, req.uid, next);
},
- ], function (err) {
- if (err) {
- return next(err);
- }
-
- var data = {
- title: '[[pages:categories]]',
- categories: categoryData,
- };
-
- if (req.path.startsWith('/api/categories') || req.path.startsWith('/categories')) {
- data.breadcrumbs = helpers.buildBreadcrumbs([{ text: data.title }]);
- }
-
- data.categories.forEach(function (category) {
- if (category && Array.isArray(category.posts) && category.posts.length) {
- category.teaser = {
- url: nconf.get('relative_path') + '/topic/' + category.posts[0].topic.slug + '/' + category.posts[0].index,
- timestampISO: category.posts[0].timestampISO,
- pid: category.posts[0].pid,
- };
+ function () {
+ var data = {
+ title: '[[pages:categories]]',
+ categories: categoryData,
+ };
+
+ if (req.path.startsWith('/api/categories') || req.path.startsWith('/categories')) {
+ data.breadcrumbs = helpers.buildBreadcrumbs([{ text: data.title }]);
}
- });
- res.render('categories', data);
- });
+ data.categories.forEach(function (category) {
+ if (category && Array.isArray(category.posts) && category.posts.length) {
+ category.teaser = {
+ url: nconf.get('relative_path') + '/post/' + category.posts[0].pid,
+ timestampISO: category.posts[0].timestampISO,
+ pid: category.posts[0].pid,
+ };
+ }
+ });
+
+ res.render('categories', data);
+ },
+ ], next);
};
-
-module.exports = categoriesController;
diff --git a/src/controllers/uploads.js b/src/controllers/uploads.js
index ab651d1325..e539c79bc6 100644
--- a/src/controllers/uploads.js
+++ b/src/controllers/uploads.js
@@ -227,11 +227,16 @@ function saveFileToLocal(uploadedFile, callback) {
file.saveFileToLocal(filename, 'files', uploadedFile.path, next);
},
function (upload, next) {
- next(null, {
+ var storedFile = {
url: nconf.get('relative_path') + upload.url,
path: upload.path,
name: uploadedFile.name,
- });
+ };
+
+ plugins.fireHook('filter:uploadStored', { uploadedFile: uploadedFile, storedFile: storedFile }, next);
+ },
+ function (data, next) {
+ next(null, data.storedFile);
},
], callback);
}
diff --git a/src/groups/membership.js b/src/groups/membership.js
index 1fc06cb5a5..8ffd845443 100644
--- a/src/groups/membership.js
+++ b/src/groups/membership.js
@@ -28,6 +28,10 @@ module.exports = function (Groups) {
return callback(new Error('[[error:invalid-data]]'));
}
+ if (!uid) {
+ return callback(new Error('[[error:invalid-uid]]'));
+ }
+
async.waterfall([
function (next) {
Groups.isMember(uid, groupName, next);
diff --git a/src/socket.io/topics/move.js b/src/socket.io/topics/move.js
index 9faffa910b..efd6562d18 100644
--- a/src/socket.io/topics/move.js
+++ b/src/socket.io/topics/move.js
@@ -30,17 +30,14 @@ module.exports = function (SocketTopics) {
topicData.tid = tid;
topics.tools.move(tid, data.cid, socket.uid, next);
},
- ], function (err) {
- if (err) {
- return next(err);
- }
-
- socketHelpers.emitToTopicAndCategory('event:topic_moved', topicData);
+ function (next) {
+ socketHelpers.emitToTopicAndCategory('event:topic_moved', topicData);
- socketHelpers.sendNotificationToTopicOwner(tid, socket.uid, 'move', 'notifications:moved_your_topic');
+ socketHelpers.sendNotificationToTopicOwner(tid, socket.uid, 'move', 'notifications:moved_your_topic');
- next();
- });
+ next();
+ },
+ ], next);
}, callback);
};
diff --git a/src/topics/delete.js b/src/topics/delete.js
index 67e8bdf230..a344ee87dd 100644
--- a/src/topics/delete.js
+++ b/src/topics/delete.js
@@ -195,6 +195,7 @@ module.exports = function (Topics) {
'cid:' + topicData.cid + ':tids',
'cid:' + topicData.cid + ':tids:pinned',
'cid:' + topicData.cid + ':tids:posts',
+ 'cid:' + topicData.cid + ':recent_tids',
'cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids',
'uid:' + topicData.uid + ':topics',
], tid, next);
diff --git a/src/topics/tools.js b/src/topics/tools.js
index 3c8835d245..743aa9d38d 100644
--- a/src/topics/tools.js
+++ b/src/topics/tools.js
@@ -50,6 +50,9 @@ module.exports = function (Topics) {
Topics[isDelete ? 'delete' : 'restore'](tid, uid, next);
},
+ function (next) {
+ categories.updateRecentTidForCid(topicData.cid, next);
+ },
function (next) {
topicData.deleted = isDelete ? 1 : 0;
@@ -258,7 +261,8 @@ module.exports = function (Topics) {
db.sortedSetsRemove([
'cid:' + topicData.cid + ':tids',
'cid:' + topicData.cid + ':tids:pinned',
- 'cid:' + topicData.cid + ':tids:posts', // post count
+ 'cid:' + topicData.cid + ':tids:posts',
+ 'cid:' + topicData.cid + ':recent_tids',
], tid, next);
},
function (next) {
@@ -280,8 +284,9 @@ module.exports = function (Topics) {
},
function (next) {
oldCid = topic.cid;
- categories.moveRecentReplies(tid, oldCid, cid);
-
+ categories.moveRecentReplies(tid, oldCid, cid, next);
+ },
+ function (next) {
async.parallel([
function (next) {
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1, next);
@@ -289,6 +294,12 @@ module.exports = function (Topics) {
function (next) {
categories.incrementCategoryFieldBy(cid, 'topic_count', 1, next);
},
+ function (next) {
+ categories.updateRecentTid(cid, tid, next);
+ },
+ function (next) {
+ categories.updateRecentTidForCid(oldCid, next);
+ },
function (next) {
Topics.setTopicFields(tid, {
cid: cid,
diff --git a/src/views/admin/partials/categories/privileges.tpl b/src/views/admin/partials/categories/privileges.tpl
index 2ec8fa2026..e55a2eaf20 100644
--- a/src/views/admin/partials/categories/privileges.tpl
+++ b/src/views/admin/partials/categories/privileges.tpl
@@ -5,7 +5,7 @@