From 68bfbfd88bcc0d0ab0922cd92a42b25b54720717 Mon Sep 17 00:00:00 2001 From: topshenyi-web Date: Sat, 7 Feb 2026 18:50:43 -0500 Subject: [PATCH 1/2] feat: endorsed topics (first post) are now visible on home page --- src/topics/endorsed.js | 9 ++ src/topics/index.js | 6 +- .../scss/modules/topics-list.scss | 96 +++++++++++++------ .../templates/partials/topics_list.tpl | 8 +- 4 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 src/topics/endorsed.js diff --git a/src/topics/endorsed.js b/src/topics/endorsed.js new file mode 100644 index 0000000000..88683db76f --- /dev/null +++ b/src/topics/endorsed.js @@ -0,0 +1,9 @@ +'use strict'; +const posts = require('../posts'); +module.exports = function (Topics) { + Topics.getEndorsedStatus = async (topics) => { + const mainPids = topics.map(topic => topic.mainPid); + const endorsers = await posts.getEndorsedUsers(mainPids); + return endorsers.map(endorsersForAPost => endorsersForAPost.length > 0); + }; +}; \ No newline at end of file diff --git a/src/topics/index.js b/src/topics/index.js index 0f9c067535..a19b13b66f 100644 --- a/src/topics/index.js +++ b/src/topics/index.js @@ -28,6 +28,7 @@ require('./posts')(Topics); require('./follow')(Topics); require('./tags')(Topics); require('./teaser')(Topics); +require('./endorsed')(Topics); Topics.scheduled = require('./scheduled'); require('./suggested')(Topics); require('./tools')(Topics); @@ -95,13 +96,14 @@ Topics.getTopicsByTids = async function (tids, options) { return data; } - const [teasers, users, userSettings, categoriesData, guestHandles, thumbs] = await Promise.all([ + const [teasers, users, userSettings, categoriesData, guestHandles, thumbs, isTopicEndorsed] = await Promise.all([ Topics.getTeasers(topics, options), user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status']), loadShowfullnameSettings(), categories.getCategoriesFields(cids, ['cid', 'name', 'slug', 'icon', 'backgroundImage', 'imageClass', 'bgColor', 'color', 'disabled']), loadGuestHandles(), Topics.thumbs.load(topics), + Topics.getEndorsedStatus(topics), ]); users.forEach((userObj, idx) => { @@ -118,6 +120,7 @@ Topics.getTopicsByTids = async function (tids, options) { categoriesMap: _.zipObject(cids, categoriesData), tidToGuestHandle: _.zipObject(guestTopics.map(t => t.tid), guestHandles), thumbs, + isTopicEndorsed, }; } @@ -140,6 +143,7 @@ Topics.getTopicsByTids = async function (tids, options) { topic.user.displayname = topic.user.username; } topic.teaser = result.teasers[i] || null; + topic.endorsed = result.isTopicEndorsed[i]; topic.isOwner = topic.uid === parseInt(uid, 10); topic.ignored = followData[i].ignoring; topic.followed = followData[i].following; diff --git a/vendor/nodebb-theme-harmony-2.1.35/scss/modules/topics-list.scss b/vendor/nodebb-theme-harmony-2.1.35/scss/modules/topics-list.scss index 714010c1f8..acf9afffa7 100644 --- a/vendor/nodebb-theme-harmony-2.1.35/scss/modules/topics-list.scss +++ b/vendor/nodebb-theme-harmony-2.1.35/scss/modules/topics-list.scss @@ -1,40 +1,74 @@ -ul.topics-list, ul.categories-list { - li { - &.deleted { - .meta, .topic-thumbs { visibility: hidden!important; } - opacity: 0.65; - } +ul.topics-list, +ul.categories-list { + li { + &.deleted { + .meta, + .topic-thumbs { + visibility: hidden !important; + } + opacity: 0.65; + } - &.selected { - background-color: mix($body-bg, $body-color, 90%); - [component="topic/select"] { - color: $success!important; - visibility: visible; - } - } - p { - margin: 0 !important; - } + &.selected { + background-color: mix($body-bg, $body-color, 90%); + [component="topic/select"] { + color: $success !important; + visibility: visible; + } + } + p { + margin: 0 !important; + } - // all other skins use link-color for unread titles - &.unread .title { - color: $link-color!important; - } + // all other skins use link-color for unread titles + &.unread .title { + color: $link-color !important; + } - .ui-sortable-handle { - cursor: move; - } + .ui-sortable-handle { + cursor: move; + } - // if only one thumb don't display - [data-numthumbs="1"] { display: none; } - } + // if only one thumb don't display + [data-numthumbs="1"] { + display: none; + } + } +} +[component="category/topic"] { + position: relative; +} +[component="category/topic/endorsed-decor"] { + .triangle { + position: absolute; + height: 100%; + width: 100%; + transform: translate(50%, 50%) rotate(45deg); + background-color: hsl(110, 90, 40); + } + position: absolute; + + right: 0; + bottom: 0; + height: 90px; + width: 90px; + overflow: hidden; + + i { + position: absolute; + right: 10px; + bottom: 10px; + color: white; + font-size: 20px; + } } // on default skin use primary color for unread titles .skin-noskin { - ul.topics-list, ul.categories-list { - li.unread .title { - color: $primary!important; - } - } + ul.topics-list, + ul.categories-list { + li.unread .title { + color: $primary !important; + } + } } diff --git a/vendor/nodebb-theme-harmony-2.1.35/templates/partials/topics_list.tpl b/vendor/nodebb-theme-harmony-2.1.35/templates/partials/topics_list.tpl index 0e247cbb7d..38bc5c006b 100644 --- a/vendor/nodebb-theme-harmony-2.1.35/templates/partials/topics_list.tpl +++ b/vendor/nodebb-theme-harmony-2.1.35/templates/partials/topics_list.tpl @@ -7,7 +7,6 @@ -
-
{{{ if !reputation:disabled }}} @@ -126,6 +124,12 @@
+ {{{ if topics.endorsed }}} +
+
+ +
+ {{{end}}} {{{end}}} From 74ece0c6b9c4b114198bcc206f4d3ee193b4c16c Mon Sep 17 00:00:00 2001 From: topshenyi-web Date: Sat, 7 Feb 2026 18:58:44 -0500 Subject: [PATCH 2/2] fix: fix tests --- public/openapi/components/schemas/TopicObject.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/openapi/components/schemas/TopicObject.yaml b/public/openapi/components/schemas/TopicObject.yaml index 9211fa14e5..d7575250b2 100644 --- a/public/openapi/components/schemas/TopicObject.yaml +++ b/public/openapi/components/schemas/TopicObject.yaml @@ -215,6 +215,8 @@ TopicObject: description: "`pinExpiry` rendered as an ISO 8601 format" index: type: number + endorsed: + type: boolean required: - tid TopicObjectSlim: @@ -305,9 +307,12 @@ TopicObjectSlim: url: type: string description: Relative path to the topic thumbnail + - type: object description: Optional properties that may or may not be present (except for `tid`, which is always present, and is only here as a hack to pass validation) properties: + endorsed: + type: boolean tid: type: number description: A topic identifier