feat: quick create on world page

This commit removes title requirement checks in NodeBB and updates the
topic creation logic so that incoming topic creation API requests
without a title just generate a title (like they already do for incoming
AP content.)
This commit is contained in:
Julian Lam
2026-02-11 15:02:29 -05:00
parent 63199ea75c
commit 5df2b8b785
6 changed files with 37 additions and 6 deletions

View File

@@ -254,6 +254,7 @@
"no-more-next-post": "You don't have more posts in this topic",
"open-composer": "Open composer",
"post-quick-reply": "Quick reply",
"post-quick-create": "Quick post",
"navigator.index": "Post %1 of %2",
"navigator.unread": "%1 unread",

View File

@@ -3,8 +3,10 @@
define('forum/world', [
'forum/infinitescroll', 'search', 'sort', 'hooks',
'alerts', 'api', 'bootbox', 'helpers', 'forum/category/tools',
'translator',
], function (infinitescroll, search, sort, hooks, alerts, api, bootbox, helpers, categoryTools, translator) {
'translator', 'quickreply',
], function (infinitescroll, search, sort, hooks,
alerts, api, bootbox, helpers, categoryTools,
translator, quickreply) {
const World = {};
$(window).on('action:ajaxify.start', function () {
@@ -14,6 +16,7 @@ define('forum/world', [
World.init = function () {
app.enterRoom('world');
categoryTools.init($('#world-feed'));
quickreply.init();
sort.handleSort('categoryTopicSort', 'world');

View File

@@ -69,6 +69,18 @@ define('quickreply', [
handle: undefined,
content: replyMsg,
};
let replyRoute = '/topics';
switch(ajaxify.data.template.name) {
case 'topic':
replyData.tid = ajaxify.data.tid;
replyRoute = `/topics/${ajaxify.data.tid}`;
break;
case 'world':
replyData.cid = '-1';
break;
}
const replyLen = replyMsg.length;
if (replyLen < parseInt(config.minimumPostLength, 10)) {
return alerts.error('[[error:content-too-short, ' + config.minimumPostLength + ']]');
@@ -78,7 +90,7 @@ define('quickreply', [
ready = false;
element.val('');
api.post(`/topics/${ajaxify.data.tid}`, replyData, function (err, data) {
api.post(replyRoute, replyData, function (err, data) {
ready = true;
if (err) {
element.val(replyMsg);

View File

@@ -7,6 +7,7 @@ const user = require('../../user');
const topics = require('../../topics');
const posts = require('../../posts');
const categories = require('../../categories');
const privileges = require('../../privileges');
const translator = require('../../translator');
const pagination = require('../../pagination');
const utils = require('../../utils');
@@ -24,7 +25,10 @@ controller.list = async function (req, res) {
const start = Math.max(0, (page - 1) * topicsPerPage);
const stop = start + topicsPerPage - 1;
const userSettings = await user.getSettings(req.uid);
const [userSettings, userPrivileges] = await Promise.all([
user.getSettings(req.uid),
privileges.categories.get('-1', req.uid),
]);
const targetUid = await user.getUidByUserslug(req.query.author);
let cidQuery = {
uid: req.uid,
@@ -40,6 +44,7 @@ controller.list = async function (req, res) {
const data = await categories.getCategoryById(cidQuery);
delete data.children;
data.sort = req.query.sort;
data.privileges = userPrivileges;
let tids;
let topicCount;

View File

@@ -10,7 +10,7 @@ const { setupApiRoute } = routeHelpers;
module.exports = function () {
const middlewares = [middleware.ensureLoggedIn];
setupApiRoute(router, 'post', '/', [middleware.checkRequired.bind(null, ['cid', 'title', 'content'])], controllers.write.topics.create);
setupApiRoute(router, 'post', '/', [middleware.checkRequired.bind(null, ['cid', 'content'])], controllers.write.topics.create);
setupApiRoute(router, 'get', '/:tid', [], controllers.write.topics.get);
setupApiRoute(router, 'post', '/:tid', [middleware.checkRequired.bind(null, ['content']), middleware.assert.topic], controllers.write.topics.reply);
setupApiRoute(router, 'delete', '/:tid', [...middlewares], controllers.write.topics.purge);

View File

@@ -3,6 +3,7 @@
const _ = require('lodash');
const winston = require('winston');
const tokenizer = require('sbd');
const db = require('../database');
const utils = require('../utils');
@@ -102,9 +103,17 @@ module.exports = function (Topics) {
privileges.users.isAdministrator(uid),
]);
data.title = String(data.title).trim();
data.tags = data.tags || [];
data.content = String(data.content || '').trimEnd();
if (data.title) {
data.title = String(data.title).trim();
} else {
const sentences = tokenizer.sentences(data.content, { sanitize: true, newline_boundaries: true });
data.title = sentences.shift();
data.generatedTitle = 1;
}
if (!isAdmin) {
Topics.checkTitle(data.title);
}
@@ -259,6 +268,7 @@ module.exports = function (Topics) {
Topics.addParentPosts([postData], uid),
Topics.syncBacklinks(postData),
Topics.markAsRead([tid], uid),
activitypub.notes.syncUserInboxes(tid, uid),
]);
// Returned data is a superset of post summary data