mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat: add new sorting option to categories
add new zset for category topics fix sorting names
This commit is contained in:
@@ -103,10 +103,10 @@
|
|||||||
"nodebb-plugin-ntfy": "1.7.3",
|
"nodebb-plugin-ntfy": "1.7.3",
|
||||||
"nodebb-plugin-spam-be-gone": "2.2.1",
|
"nodebb-plugin-spam-be-gone": "2.2.1",
|
||||||
"nodebb-rewards-essentials": "1.0.0",
|
"nodebb-rewards-essentials": "1.0.0",
|
||||||
"nodebb-theme-harmony": "1.2.36",
|
"nodebb-theme-harmony": "1.2.37",
|
||||||
"nodebb-theme-lavender": "7.1.7",
|
"nodebb-theme-lavender": "7.1.7",
|
||||||
"nodebb-theme-peace": "2.2.4",
|
"nodebb-theme-peace": "2.2.4",
|
||||||
"nodebb-theme-persona": "13.3.10",
|
"nodebb-theme-persona": "13.3.11",
|
||||||
"nodebb-widget-essentials": "7.0.15",
|
"nodebb-widget-essentials": "7.0.15",
|
||||||
"nodemailer": "6.9.11",
|
"nodemailer": "6.9.11",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
"sorting.post-default": "Default Post Sorting",
|
"sorting.post-default": "Default Post Sorting",
|
||||||
"sorting.oldest-to-newest": "Oldest to Newest",
|
"sorting.oldest-to-newest": "Oldest to Newest",
|
||||||
"sorting.newest-to-oldest": "Newest to Oldest",
|
"sorting.newest-to-oldest": "Newest to Oldest",
|
||||||
|
"sorting.recently-replied": "Recently Replied",
|
||||||
|
"sorting.recently-created": "Recently Created",
|
||||||
"sorting.most-votes": "Most Votes",
|
"sorting.most-votes": "Most Votes",
|
||||||
"sorting.most-posts": "Most Posts",
|
"sorting.most-posts": "Most Posts",
|
||||||
|
"sorting.most-views": "Most Views",
|
||||||
"sorting.topic-default": "Default Topic Sorting",
|
"sorting.topic-default": "Default Topic Sorting",
|
||||||
"length": "Post Length",
|
"length": "Post Length",
|
||||||
"post-queue": "Post Queue",
|
"post-queue": "Post Queue",
|
||||||
|
|||||||
@@ -206,6 +206,8 @@
|
|||||||
"sort-by": "Sort by",
|
"sort-by": "Sort by",
|
||||||
"oldest-to-newest": "Oldest to Newest",
|
"oldest-to-newest": "Oldest to Newest",
|
||||||
"newest-to-oldest": "Newest to Oldest",
|
"newest-to-oldest": "Newest to Oldest",
|
||||||
|
"recently-replied": "Recently Replied",
|
||||||
|
"recently-created": "Recently Created",
|
||||||
"most-votes": "Most Votes",
|
"most-votes": "Most Votes",
|
||||||
"most-posts": "Most Posts",
|
"most-posts": "Most Posts",
|
||||||
"most-views": "Most Views",
|
"most-views": "Most Views",
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ categoriesAPI.getTopics = async (caller, data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const infScrollTopicsPerPage = 20;
|
const infScrollTopicsPerPage = 20;
|
||||||
const sort = data.sort || data.categoryTopicSort || meta.config.categoryTopicSort || 'newest_to_oldest';
|
const sort = data.sort || data.categoryTopicSort || meta.config.categoryTopicSort || 'recently_replied';
|
||||||
|
|
||||||
let start = Math.max(0, parseInt(data.after || 0, 10));
|
let start = Math.max(0, parseInt(data.after || 0, 10));
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,9 @@ module.exports = function (Categories) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.getTopicIds = async function (data) {
|
Categories.getTopicIds = async function (data) {
|
||||||
const [pinnedTids, set, direction] = await Promise.all([
|
const [pinnedTids, set] = await Promise.all([
|
||||||
Categories.getPinnedTids({ ...data, start: 0, stop: -1 }),
|
Categories.getPinnedTids({ ...data, start: 0, stop: -1 }),
|
||||||
Categories.buildTopicsSortedSet(data),
|
Categories.buildTopicsSortedSet(data),
|
||||||
Categories.getSortedSetRangeDirection(data.sort),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const totalPinnedCount = pinnedTids.length;
|
const totalPinnedCount = pinnedTids.length;
|
||||||
@@ -62,12 +61,11 @@ module.exports = function (Categories) {
|
|||||||
|
|
||||||
const stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1;
|
const stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1;
|
||||||
let normalTids;
|
let normalTids;
|
||||||
const reverse = direction === 'highest-to-lowest';
|
|
||||||
if (Array.isArray(set)) {
|
if (Array.isArray(set)) {
|
||||||
const weights = set.map((s, index) => (index ? 0 : 1));
|
const weights = set.map((s, index) => (index ? 0 : 1));
|
||||||
normalTids = await db[reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop, weights: weights });
|
normalTids = await db.getSortedSetRevIntersect({ sets: set, start: start, stop: stop, weights: weights });
|
||||||
} else {
|
} else {
|
||||||
normalTids = await db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop);
|
normalTids = await db.getSortedSetRevRange(set, start, stop);
|
||||||
}
|
}
|
||||||
normalTids = normalTids.filter(tid => !pinnedTids.includes(tid));
|
normalTids = normalTids.filter(tid => !pinnedTids.includes(tid));
|
||||||
return pinnedTidsOnPage.concat(normalTids);
|
return pinnedTidsOnPage.concat(normalTids);
|
||||||
@@ -92,16 +90,16 @@ module.exports = function (Categories) {
|
|||||||
|
|
||||||
Categories.buildTopicsSortedSet = async function (data) {
|
Categories.buildTopicsSortedSet = async function (data) {
|
||||||
const { cid } = data;
|
const { cid } = data;
|
||||||
let set = `cid:${cid}:tids`;
|
const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'recently_replied';
|
||||||
const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest';
|
const sortToSet = {
|
||||||
|
recently_replied: `cid:${cid}:tids`,
|
||||||
|
recently_created: `cid:${cid}:tids:create`,
|
||||||
|
most_posts: `cid:${cid}:tids:posts`,
|
||||||
|
most_votes: `cid:${cid}:tids:votes`,
|
||||||
|
most_views: `cid:${cid}:tids:views`,
|
||||||
|
};
|
||||||
|
|
||||||
if (sort === 'most_posts') {
|
let set = sortToSet.hasOwnProperty(sort) ? sortToSet[sort] : `cid:${cid}:tids`;
|
||||||
set = `cid:${cid}:tids:posts`;
|
|
||||||
} else if (sort === 'most_votes') {
|
|
||||||
set = `cid:${cid}:tids:votes`;
|
|
||||||
} else if (sort === 'most_views') {
|
|
||||||
set = `cid:${cid}:tids:views`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.tag) {
|
if (data.tag) {
|
||||||
if (Array.isArray(data.tag)) {
|
if (Array.isArray(data.tag)) {
|
||||||
@@ -123,7 +121,8 @@ module.exports = function (Categories) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.getSortedSetRangeDirection = async function (sort) {
|
Categories.getSortedSetRangeDirection = async function (sort) {
|
||||||
sort = sort || 'newest_to_oldest';
|
console.warn('[deprecated] Will be removed in 4.x');
|
||||||
|
sort = sort || 'recently_replied';
|
||||||
const direction = ['newest_to_oldest', 'most_posts', 'most_votes', 'most_views'].includes(sort) ? 'highest-to-lowest' : 'lowest-to-highest';
|
const direction = ['newest_to_oldest', 'most_posts', 'most_votes', 'most_views'].includes(sort) ? 'highest-to-lowest' : 'lowest-to-highest';
|
||||||
const result = await plugins.hooks.fire('filter:categories.getSortedSetRangeDirection', {
|
const result = await plugins.hooks.fire('filter:categories.getSortedSetRangeDirection', {
|
||||||
sort: sort,
|
sort: sort,
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ apiController.loadConfig = async function (req) {
|
|||||||
uid: req.uid,
|
uid: req.uid,
|
||||||
'cache-buster': meta.config['cache-buster'] || '',
|
'cache-buster': meta.config['cache-buster'] || '',
|
||||||
topicPostSort: meta.config.topicPostSort || 'oldest_to_newest',
|
topicPostSort: meta.config.topicPostSort || 'oldest_to_newest',
|
||||||
categoryTopicSort: meta.config.categoryTopicSort || 'newest_to_oldest',
|
categoryTopicSort: meta.config.categoryTopicSort || 'recently_replied',
|
||||||
csrf_token: req.uid >= 0 ? generateToken(req) : false,
|
csrf_token: req.uid >= 0 ? generateToken(req) : false,
|
||||||
searchEnabled: plugins.hooks.hasListeners('filter:search.query'),
|
searchEnabled: plugins.hooks.hasListeners('filter:search.query'),
|
||||||
searchDefaultInQuick: meta.config.searchDefaultInQuick || 'titles',
|
searchDefaultInQuick: meta.config.searchDefaultInQuick || 'titles',
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ const categoryController = module.exports;
|
|||||||
|
|
||||||
const url = nconf.get('url');
|
const url = nconf.get('url');
|
||||||
const relative_path = nconf.get('relative_path');
|
const relative_path = nconf.get('relative_path');
|
||||||
const validSorts = ['newest_to_oldest', 'oldest_to_newest', 'most_posts', 'most_votes', 'most_views'];
|
const validSorts = [
|
||||||
|
'recently_replied', 'recently_created', 'most_posts', 'most_votes', 'most_views',
|
||||||
|
];
|
||||||
|
|
||||||
categoryController.get = async function (req, res, next) {
|
categoryController.get = async function (req, res, next) {
|
||||||
const cid = req.params.category_id;
|
const cid = req.params.category_id;
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ module.exports = function (Topics) {
|
|||||||
db.sortedSetsRemove([
|
db.sortedSetsRemove([
|
||||||
`cid:${topicData.cid}:tids`,
|
`cid:${topicData.cid}:tids`,
|
||||||
`cid:${topicData.cid}:tids:pinned`,
|
`cid:${topicData.cid}:tids:pinned`,
|
||||||
|
`cid:${topicData.cid}:tids:create`,
|
||||||
`cid:${topicData.cid}:tids:posts`,
|
`cid:${topicData.cid}:tids:posts`,
|
||||||
`cid:${topicData.cid}:tids:lastposttime`,
|
`cid:${topicData.cid}:tids:lastposttime`,
|
||||||
`cid:${topicData.cid}:tids:votes`,
|
`cid:${topicData.cid}:tids:votes`,
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ Scheduled.pin = async function (tid, topicData) {
|
|||||||
db.sortedSetAdd(`cid:${topicData.cid}:tids:pinned`, Date.now(), tid),
|
db.sortedSetAdd(`cid:${topicData.cid}:tids:pinned`, Date.now(), tid),
|
||||||
db.sortedSetsRemove([
|
db.sortedSetsRemove([
|
||||||
`cid:${topicData.cid}:tids`,
|
`cid:${topicData.cid}:tids`,
|
||||||
|
`cid:${topicData.cid}:tids:create`,
|
||||||
`cid:${topicData.cid}:tids:posts`,
|
`cid:${topicData.cid}:tids:posts`,
|
||||||
`cid:${topicData.cid}:tids:votes`,
|
`cid:${topicData.cid}:tids:votes`,
|
||||||
`cid:${topicData.cid}:tids:views`,
|
`cid:${topicData.cid}:tids:views`,
|
||||||
@@ -96,6 +97,7 @@ function unpin(tid, topicData) {
|
|||||||
db.sortedSetRemove(`cid:${topicData.cid}:tids:pinned`, tid),
|
db.sortedSetRemove(`cid:${topicData.cid}:tids:pinned`, tid),
|
||||||
db.sortedSetAddBulk([
|
db.sortedSetAddBulk([
|
||||||
[`cid:${topicData.cid}:tids`, topicData.lastposttime, tid],
|
[`cid:${topicData.cid}:tids`, topicData.lastposttime, tid],
|
||||||
|
[`cid:${topicData.cid}:tids:create`, topicData.timestamp, tid],
|
||||||
[`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid],
|
[`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid],
|
||||||
[`cid:${topicData.cid}:tids:votes`, parseInt(topicData.votes, 10) || 0, tid],
|
[`cid:${topicData.cid}:tids:votes`, parseInt(topicData.votes, 10) || 0, tid],
|
||||||
[`cid:${topicData.cid}:tids:views`, topicData.viewcount, tid],
|
[`cid:${topicData.cid}:tids:views`, topicData.viewcount, tid],
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ module.exports = function (Topics) {
|
|||||||
const cid = await Topics.getTopicField(tid, 'cid');
|
const cid = await Topics.getTopicField(tid, 'cid');
|
||||||
const tids = cutoff === 0 ?
|
const tids = cutoff === 0 ?
|
||||||
await db.getSortedSetRevRange(`cid:${cid}:tids:lastposttime`, 0, 9) :
|
await db.getSortedSetRevRange(`cid:${cid}:tids:lastposttime`, 0, 9) :
|
||||||
await db.getSortedSetRevRangeByScore(`cid:${cid}:tids:lastposttime`, 0, 9, '+inf', Date.now() - cutoff);
|
await db.getSortedSetRevRangeByScore(`cid:${cid}:tids:lastposttime`, 0, 10, '+inf', Date.now() - cutoff);
|
||||||
return _.shuffle(tids.map(Number).filter(_tid => _tid !== tid));
|
return _.shuffle(tids.map(Number).filter(_tid => _tid !== tid));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ module.exports = function (Topics) {
|
|||||||
promises.push(db.sortedSetAdd(`cid:${topicData.cid}:tids:pinned`, Date.now(), tid));
|
promises.push(db.sortedSetAdd(`cid:${topicData.cid}:tids:pinned`, Date.now(), tid));
|
||||||
promises.push(db.sortedSetsRemove([
|
promises.push(db.sortedSetsRemove([
|
||||||
`cid:${topicData.cid}:tids`,
|
`cid:${topicData.cid}:tids`,
|
||||||
|
`cid:${topicData.cid}:tids:create`,
|
||||||
`cid:${topicData.cid}:tids:posts`,
|
`cid:${topicData.cid}:tids:posts`,
|
||||||
`cid:${topicData.cid}:tids:votes`,
|
`cid:${topicData.cid}:tids:votes`,
|
||||||
`cid:${topicData.cid}:tids:views`,
|
`cid:${topicData.cid}:tids:views`,
|
||||||
@@ -180,6 +181,7 @@ module.exports = function (Topics) {
|
|||||||
promises.push(Topics.deleteTopicField(tid, 'pinExpiry'));
|
promises.push(Topics.deleteTopicField(tid, 'pinExpiry'));
|
||||||
promises.push(db.sortedSetAddBulk([
|
promises.push(db.sortedSetAddBulk([
|
||||||
[`cid:${topicData.cid}:tids`, topicData.lastposttime, tid],
|
[`cid:${topicData.cid}:tids`, topicData.lastposttime, tid],
|
||||||
|
[`cid:${topicData.cid}:tids:create`, topicData.timestamp, tid],
|
||||||
[`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid],
|
[`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid],
|
||||||
[`cid:${topicData.cid}:tids:votes`, parseInt(topicData.votes, 10) || 0, tid],
|
[`cid:${topicData.cid}:tids:votes`, parseInt(topicData.votes, 10) || 0, tid],
|
||||||
[`cid:${topicData.cid}:tids:views`, topicData.viewcount, tid],
|
[`cid:${topicData.cid}:tids:views`, topicData.viewcount, tid],
|
||||||
@@ -242,6 +244,7 @@ module.exports = function (Topics) {
|
|||||||
const tags = await Topics.getTopicTags(tid);
|
const tags = await Topics.getTopicTags(tid);
|
||||||
await db.sortedSetsRemove([
|
await db.sortedSetsRemove([
|
||||||
`cid:${topicData.cid}:tids`,
|
`cid:${topicData.cid}:tids`,
|
||||||
|
`cid:${topicData.cid}:tids:create`,
|
||||||
`cid:${topicData.cid}:tids:pinned`,
|
`cid:${topicData.cid}:tids:pinned`,
|
||||||
`cid:${topicData.cid}:tids:posts`,
|
`cid:${topicData.cid}:tids:posts`,
|
||||||
`cid:${topicData.cid}:tids:votes`,
|
`cid:${topicData.cid}:tids:votes`,
|
||||||
@@ -264,6 +267,7 @@ module.exports = function (Topics) {
|
|||||||
bulk.push([`cid:${cid}:tids:pinned`, Date.now(), tid]);
|
bulk.push([`cid:${cid}:tids:pinned`, Date.now(), tid]);
|
||||||
} else {
|
} else {
|
||||||
bulk.push([`cid:${cid}:tids`, topicData.lastposttime, tid]);
|
bulk.push([`cid:${cid}:tids`, topicData.lastposttime, tid]);
|
||||||
|
bulk.push([`cid:${cid}:tids:create`, topicData.timestamp, tid]);
|
||||||
bulk.push([`cid:${cid}:tids:posts`, topicData.postcount, tid]);
|
bulk.push([`cid:${cid}:tids:posts`, topicData.postcount, tid]);
|
||||||
bulk.push([`cid:${cid}:tids:votes`, votes, tid]);
|
bulk.push([`cid:${cid}:tids:votes`, votes, tid]);
|
||||||
bulk.push([`cid:${cid}:tids:views`, topicData.viewcount, tid]);
|
bulk.push([`cid:${cid}:tids:views`, topicData.viewcount, tid]);
|
||||||
|
|||||||
31
src/upgrades/3.7.0/category-tid-created-zset.js
Normal file
31
src/upgrades/3.7.0/category-tid-created-zset.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
const db = require('../../database');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'New sorted set cid:<cid>:tids:create',
|
||||||
|
timestamp: Date.UTC(2024, 2, 4),
|
||||||
|
method: async function () {
|
||||||
|
const { progress } = this;
|
||||||
|
const batch = require('../../batch');
|
||||||
|
await batch.processSortedSet('topics:tid', async (tids) => {
|
||||||
|
let topicData = await db.getObjectsFields(
|
||||||
|
tids.map(tid => `topic:${tid}`),
|
||||||
|
['tid', 'cid', 'timestamp']
|
||||||
|
);
|
||||||
|
topicData = topicData.filter(Boolean);
|
||||||
|
topicData.forEach((t) => {
|
||||||
|
t.timestamp = t.timestamp || Date.now();
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sortedSetAddBulk(
|
||||||
|
topicData.map(t => ([`cid:${t.cid}:tids:create`, t.timestamp, t.tid]))
|
||||||
|
);
|
||||||
|
|
||||||
|
progress.incr(tids.length);
|
||||||
|
}, {
|
||||||
|
progress: this.progress,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
37
src/upgrades/3.7.0/change-category-sort-settings.js
Normal file
37
src/upgrades/3.7.0/change-category-sort-settings.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
const db = require('../../database');
|
||||||
|
const batch = require('../../batch');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Change category sort settings',
|
||||||
|
timestamp: Date.UTC(2024, 2, 4),
|
||||||
|
method: async function () {
|
||||||
|
const { progress } = this;
|
||||||
|
|
||||||
|
const currentSort = await db.getObjectField('config', 'categoryTopicSort');
|
||||||
|
if (currentSort === 'oldest_to_newest' || currentSort === 'newest_to_oldest') {
|
||||||
|
await db.setObjectField('config', 'categoryTopicSort', 'recently_replied');
|
||||||
|
}
|
||||||
|
|
||||||
|
await batch.processSortedSet('users:joindate', async (uids) => {
|
||||||
|
progress.incr(uids.length);
|
||||||
|
const usersSettings = await db.getObjects(uids.map(uid => `user:${uid}:settings`));
|
||||||
|
const bulkSet = [];
|
||||||
|
usersSettings.forEach((userSetting, i) => {
|
||||||
|
if (userSetting && (
|
||||||
|
userSetting.categoryTopicSort === 'newest_to_oldest' ||
|
||||||
|
userSetting.categoryTopicSort === 'oldest_to_newest')) {
|
||||||
|
bulkSet.push([
|
||||||
|
`user:${uids[i]}:settings`, { categoryTopicSort: 'recently_replied' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await db.setObjectBulk(bulkSet);
|
||||||
|
}, {
|
||||||
|
batch: 500,
|
||||||
|
progress: progress,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -67,7 +67,7 @@ module.exports = function (User) {
|
|||||||
settings.userLang = settings.userLang || meta.config.defaultLang || 'en-GB';
|
settings.userLang = settings.userLang || meta.config.defaultLang || 'en-GB';
|
||||||
settings.acpLang = settings.acpLang || settings.userLang;
|
settings.acpLang = settings.acpLang || settings.userLang;
|
||||||
settings.topicPostSort = getSetting(settings, 'topicPostSort', 'oldest_to_newest');
|
settings.topicPostSort = getSetting(settings, 'topicPostSort', 'oldest_to_newest');
|
||||||
settings.categoryTopicSort = getSetting(settings, 'categoryTopicSort', 'newest_to_oldest');
|
settings.categoryTopicSort = getSetting(settings, 'categoryTopicSort', 'recently_replied');
|
||||||
settings.followTopicsOnCreate = parseInt(getSetting(settings, 'followTopicsOnCreate', 1), 10) === 1;
|
settings.followTopicsOnCreate = parseInt(getSetting(settings, 'followTopicsOnCreate', 1), 10) === 1;
|
||||||
settings.followTopicsOnReply = parseInt(getSetting(settings, 'followTopicsOnReply', 0), 10) === 1;
|
settings.followTopicsOnReply = parseInt(getSetting(settings, 'followTopicsOnReply', 0), 10) === 1;
|
||||||
settings.upvoteNotifFreq = getSetting(settings, 'upvoteNotifFreq', 'all');
|
settings.upvoteNotifFreq = getSetting(settings, 'upvoteNotifFreq', 'all');
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="categoryTopicSort">[[admin/settings/post:sorting.topic-default]]</label>
|
<label class="form-label" for="categoryTopicSort">[[admin/settings/post:sorting.topic-default]]</label>
|
||||||
<select id="categoryTopicSort" class="form-select" data-field="categoryTopicSort">
|
<select id="categoryTopicSort" class="form-select" data-field="categoryTopicSort">
|
||||||
<option value="oldest_to_newest">[[admin/settings/post:sorting.oldest-to-newest]]</option>
|
<option value="recently_replied">[[admin/settings/post:sorting.recently-replied]]</option>
|
||||||
<option value="newest_to_oldest">[[admin/settings/post:sorting.newest-to-oldest]]</option>
|
<option value="recently_created">[[admin/settings/post:sorting.recently-created]]</option>
|
||||||
<option value="most_posts">[[admin/settings/post:sorting.most-posts]]</option>
|
<option value="most_posts">[[admin/settings/post:sorting.most-posts]]</option>
|
||||||
|
<option value="most_votes">[[admin/settings/post:sorting.most-votes]]</option>
|
||||||
|
<option value="most_views">[[admin/settings/post:sorting.most-views]]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user