In nodeBB how to display last five participants avatar in topic list page
-
Hi,
In nodeBB how to display last / most five participants avatar in topic list page. Is their any plugin for this ?
For example :-
-
You can use the sorted set
tid:<tid>:posters
for this. It stores the user ids who have made posts in the topic and the score is how many posts they have. Use thefilter:topics.get
hook and add the users with most posts in the topic to each topic object like below.myPlugin.filterTopicsGet = async (hookData) => { // get the posters of the topics const keys = hookData.topics.map(t => `tid:${t.tid}:posters`); const posters = await db.getSortedSetsMembers(keys); // get the uniq uids const uniqUids = _.uniq(_.flatten(posters)); // load the data for the uniq uids const userData = await users.getUsersFields(uniqUids, ['username', 'userslug', 'picture']); const uidToUserData = _.zipObject(uniqUids, userData); // set the 'posters' field on each topic hookData.topics.forEach((t, index) => { const posterUids = posters[index].reverse().slice(0, 4); t.posters = posterUids.map(uid => uidToUserData[uid]); }); return hookData; };
This will create a
posters
field on each topic object and you can use it in yourtopics_list.tpl
template. -
Hi Baris,
thank you for sharing code...I add this using create custom plugin nodebb-plugin-posters in directory "..\NodeBB\node_modules\nodebb-plugin-posters", and then create two new files plugin.json , and index.js
in plugin.json -
{ "id": "nodebb-plugin-posters", "name": "Posters", "description": "This is the custom plugin designed for display top most 5 active users poster / avatar will be display in the topic list column.", "url": "https://github.com/NodeBB/nodebb-plugin-posters", "library": "./library.js", "hooks": [ { "hook": "filter:topics.get", "method": "filterTopics" } ] }
And in index.js
/** * You can run these tests by executing `npx mocha test/plugins-installed.js` * from the NodeBB root folder. The regular test runner will also run these * tests. * * Keep in mind tests do not activate all plugins, so if you are testing * hook listeners, socket.io, or mounted routes, you will need to add your * plugin to `config.json`, e.g. * * { * "test_plugins": [ * "nodebb-plugin-posters" * ] * } */ "use strict"; const Plugin = {}; myPlugin.filterTopicsGet = async (hookData) => { // get the posters of the topics const keys = hookData.topics.map(t => `tid:${t.tid}:posters`); const posters = await db.getSortedSetsMembers(keys); // get the uniq uids const uniqUids = _.uniq(_.flatten(posters)); // load the data for the uniq uids const userData = await users.getUsersFields(uniqUids, ['username', 'userslug', 'picture']); const uidToUserData = _.zipObject(uniqUids, userData); // set the 'posters' field on each topic hookData.topics.forEach((t, index) => { const posterUids = posters[index].reverse().slice(0, 4); t.posters = posterUids.map(uid => uidToUserData[uid]); }); return hookData; };
and for front end topic-list.tpl
<div class="col-md-2 content"> <ul> {topic.posters.forEach(function(poster) { <li> <a href="{config.relative_path}/user/{poster.username}"> <img src="{poster.picture}" alt="{poster.username}" /> {poster.username} </a> ({poster.postCount} posts) </li> })} </ul> </div>
Din't get result as expected .
Could you please guide me where i made mistakes ?
-
{ "hook": "filter:topics.get", "method": "filterTopics" }
the method name here needs to match the method name inindex.js
so it should befilterTopicsGet
in both places.Also
nodebb-plugin-posters
needs to be activated as a plugin with./nodebb activate nodebb-plugin-posters
.For more info see https://docs.nodebb.org/development/plugins/
-
Hay @baris ,
I did this Plugin is activated now, but on the front end users posters are not displaying ,
<ul> {topic.posters.forEach(function(poster) { <li> <a href="{config.relative_path}/user/{poster.userslug}"> <img src="{poster.picture}" alt="{poster.userslug}" /> {poster.username} </a> ({poster.postCount} posts) </li> })} </ul>
O/P :-
-
Your template syntax is wrong. There is no
forEach
, it should look like this:<ul> {{{ each topic.posters }}} <li> <a href="{config.relative_path}/user/{./userslug}"> <img src="{./picture}" alt="{./userslug}" /> {./username} </a> ({/.postCount} posts) </li> {{{ end }}} </ul>
Also make sure the data is there, you can check by looking at
ajaxify.data.topics
in your browser console. -
Hi i tried to do this as well , Actually this hook is not called "myPlugin.filterTopicsGet = async (hookData) => {..."
but dint get any luck yet
Here is the object i have seen
[ { "cid": 1, "lastposttime": 1683791375452, "mainPid": 3, "postcount": 3, "slug": "3/there-is-new-topics-in-this-category-post-1", "tid": 3, "timestamp": 1683281405155, "title": "There is new topics in this category post 1", "uid": 2, "viewcount": 6, "postercount": 3, "teaserPid": 6, "downvotes": 0, "upvotes": 1, "deleted": 0, "locked": 0, "pinned": 0, "pinExpiry": 0, "deleterUid": 0, "titleRaw": "There is new topics in this category post 1", "timestampISO": "2023-05-05T10:10:05.155Z", "scheduled": false, "lastposttimeISO": "2023-05-11T07:49:35.452Z", "pinExpiryISO": "", "votes": 1, "tags": [], "thumbs": [], "category": { "cid": 1, "name": "Announcements", "slug": "1/announcements", "icon": "fa-bullhorn", "backgroundImage": "", "imageClass": "cover", "bgColor": "#fda34b", "color": "#ffffff", "disabled": 0 }, "user": { "uid": 2, "username": "Vijay Kumavat", "userslug": "vijay-kumavat", "reputation": 1, "postcount": 2, "picture": null, "signature": "VSK", "banned": false, "status": "offline", "displayname": "Vijay Kumavat", "icon:text": "V", "icon:bgColor": "#9c27b0", "banned_until_readable": "Not Banned" }, "teaser": { "pid": 6, "uid": 3, "timestamp": 1683791375452, "tid": 3, "content": "<p dir=\"auto\"><a class=\"plugin-mentions-user plugin-mentions-a\" href=\"http://localhost:4567/uid/2\">@Vijay-Kumavat</a> , this is reply on new user</p>\n<p dir=\"auto\">Sidhharth</p>\n", "timestampISO": "2023-05-11T07:49:35.452Z", "user": { "uid": 3, "username": "Siddharth", "userslug": "siddharth", "picture": null, "displayname": "Siddharth", "icon:text": "S", "icon:bgColor": "#607d8b" }, "index": 3 }, "isOwner": false, "ignored": false, "unread": false, "bookmark": 1, "unreplied": false, "icons": [], "posters": [ { "username": "admin", "userslug": "admin", "picture": null, "uid": 1, "displayname": "admin", "icon:text": "A", "icon:bgColor": "#673ab7" }, { "username": "Vijay Kumavat", "userslug": "vijay-kumavat", "picture": null, "uid": 2, "displayname": "Vijay Kumavat", "icon:text": "V", "icon:bgColor": "#9c27b0" }, { "username": "Siddharth", "userslug": "siddharth", "picture": null, "uid": 3, "displayname": "Siddharth", "icon:text": "S", "icon:bgColor": "#607d8b" } ], "index": 0 }, { .... }, { .... }, ]
-
If your hook is not called, then check if the plugin is active and there are no errors at startup. The data won't be there if the hook isn't executed.
Plugin.json should have this
{ "hook": "filter:topics.get", "method": "filterTopicsGet" }
if you havemyPlugin.filterTopicsGet
in your plugin code. -
Hi @baris ,
Now hook is executed properly after removing some errors shown in log section, then after
console.log(hookData);
before return hookData, its showing me as well in log section.
but i think .tpl code is not showing anything i am using this in topics_list.tpl
<ul> {{{each topic.posters}}} <li> <a href="./user/{./userslug}"> <img src="{./picture}" alt="{./userslug}" /> {./username} </a> ({/.postCount} posts) </li> {{{ end }}} </ul>
Its shows me empty like <ul></ul> this in inspect element.
I can share you my custom plugin file as well. please help me to rectify this one.
-
Thanks @baris ,
i got it now, i was made mistake here
{{{each topic.posters}}}
it should be like this
{{{each topics.posters}}}
Thanks again you save me here..
-
@vijay-kumavat @baris is there any intention to make this formally available via NPM as a plugin? Whilst it's very "Discourse-esque", it does add an additional feature set to NodeBB which I think perhaps should even be in core?
-
Hi
I dont have experience in this, but i stored this files on my git acc. https://github.com/KumavatVjy/nodebb-plugin-posters . Here you will find the plugin files "nodebb-plugin-posters". -
@vijay-kumavat Thanks. I've forked the repository as I intend to add more functionality to it eventually Have it running in DEV under the Harmony theme (whereas you are using Persona by the looks of it).
-
@phenomlab , @baris Thank you too..
-
I will try to fetch user details in something like that on click/hover on user avatar.
i need your help in that once i start on this. Thank you
-
Possible to upload on NPM @phenomlab @vijay-kumavat for testing it ?