Plugin setup
-
Do add data for use in template this is what you need to do.
- in plugin.json add the hook, which you already did.
"hooks": [ { "hook": "filter:recent.build", "method": "filterRecentBuild" } ],
- in
lib/theme.js
add the same methodfilterRecentBuild
library.filterRecentBuild = async (hookData) { hookData.templateData.topicsList = [] // fill it with data return hookData; }
Now when you load the
/recent
page ajaxify.data will havetopicsList
property. You don't need to do anything inpublic/codename.js
.filter:recent.build
is a server side hook, you can't listen to it withhooks.on('filter:recent.build')
-
Maybe this is where I am confused. If you see https://jbrowns.com/ and look at the bottom of the page, you will see the Latest Topics section I am trying to build out. So I am confused about loading the /recent page. Unless you are referring to:
const filterRecentBuild = require.main.require('./recent')
-
If you are trying to build a latest topics widget, than you don't need
filter:recent.build
, just add a new widget. See this commit that adds a new widget in the widget-essentials plugin. https://github.com/NodeBB/nodebb-widget-essentials/commit/d73fdb2d90d6359b22b9d1c50bafb56ac2b0c038. That's all you need to add a new widget, then you can place it on any page you want.Adding data via
filter:recent.build
only adds it on the /recent page. NodeBB fires a hook on every page in the formfilter:<template_name>.build
likefilter:recent.build
,filter:categories.build
,filter:users.build
and so on. -
Ok, so this is a little different than I expected. If I wanted to build out themes with different information on different pages. (For example on the main page (/categories or /), if you notice on the right side, there will be different stats, etc. and at the bottom, there will be some latest topics), and then throughout this page there will be notification badges, modal items (hovering over different items), etc. Unless I build a client JS file to literally call the api with axios or something along those line, everything would have to be a widget? I guess what I am saying the library.js file cannot call actual API items unless it is on the page that the API is on. (for example /topics will get the topics API)
WAIT!!! I think I figured something out... This Widget is NOT in the admin panel... Let me look this over. Thank you
-
This post is deleted!
-
I guess I do not know what I am doing. I cannot find a working example of a widget, plugin, or anything that works or that is usable on my theme. So, I guess I cannot figure it out. Thank you for trying to help.
-
They are documented at https://docs.nodebb.org/development/plugins/ and https://docs.nodebb.org/development/widgets/
From what I understand you want to add custom data to the /categories page, you can either build widgets that have this data and place them on the categories page or you can use
filter:categories.build
server side hook and add that data intotemplateData
and use it in your tpl.If they are only going to be used on the /categories page then use
filter:categories.build
if you want to place them on multiple pages build them as widgets. -
Thank you baris, you have been extremely patient and very courteous with me. I spent the first week of my 3 weeks' vacation trying to build a theme that would match my front page and then it just got to the point where I was constantly banging my head on the wall trying to get 1 thing working. The template works, kind of, but that took 3 days to build, when it only took me 3 hours to build the VueJS page with its own components, views, and models (Yes an MVC in an MVVM language, WHY ME?). I used axios to get /api/users, /api/topics, etc, and it worked quite nicely until I didn't realize that my template would go away when I npm installed. (That is my own fault in many ways, 1. It is documented ALL OVER THE PLACE, not to do that. 2. I just completely forgot). That caused me to get beat up pretty good. So I started over again. This time, linked the nodebb-theme-codename from my home folder to the node_modules folder (as documented). Got everything looking back to normal, then widgets, libraries... I just couldn't make any sense of the documents. An example: Widgets
(copy and pasted from that link)
Registering your widget
Listen to this hook to register your widget:
"hook": "filter:widgets.getWidgets", "method": "defineWidgets", "callbacked": true
Pass this back in the array:
{ widget: "widget_namespace", name: "My Widget", description: "Short description of what it does.", content: "<input type=\"text\" name=\"myKey\" class=\"form-control\" />" }
Content defines the form that is displayed to customize your widget in the admin panel.
My understanding of the documents:
I put the first part in my
plugins.json
:{ "id": "nodebb-theme-codename", "url": "https://github.com/girls-whocode/nodebb-theme-codename", "library": "lib/library.js", "hooks": [ { "hook": "filter:widgets.getWidgets", "method": "topPosters", "callbacked": true } ], "staticDirs": { "static": "static", "inter": "node_modules/@fontsource/inter/files", "poppins": "node_modules/@fontsource/poppins/files" }, "scss": [ "scss/codename.scss" ], "scripts": [ "public/codename.js" ], "templates": "templates" }
The second part, I have no idea what to do with it or where to put it. So, I start searching, looking at other code, looking at other plugins, couldn't see what this was referring to.
Then I opened my
lib/library.js
and at the bottom I added this:Widget.init = async function (params) { // winston.info('Custom widget initialized', params); // console.log('Custom widget initialized', params); }; Widget.topPosters = async function (widgets) { widgets.push({ sidebar: true, widget: 'top_posters', // Unique ID for your widget name: 'CNJ Top Posters', // Display name description: 'Top posters widget for CodeNameJessica', // Description content: 'widgets/top_posters', // Path to the template file }); winston.info('widgets pushed', widgets); console.log('widgets pushed', widgets); return widgets; }; Widget.render = async function () { const topPosters = await user.getTopUsersByPosts({ limit: 5 }); console.info(user); console.log(user); return { title: 'Top Posters', posters: topPosters.map(user => ({ username: user.username, posts: user.postCount, })), }; }; module.exports = Widget;
I created a `templates/widgets/top_posters.tpl'
<div data-widget-area="sidebar" class="nodebbWidget__content--wrap"> <div data-blocktitle="Top User Postings" data-controller="core.front.widgets.block" class="nodebbWidget nodebbWidget--vertical"> <h3 class="nodebbWidget__header">Top User Postings</h3> <div class="nodebbWidget__content"> {{{ each users }}} <a href="{config.relative_path}/user/{./userslug}" data-uid="{./uid}" class="btn-ghost ff-secondary align-items-start justify-content-start p-2 ff-base"> {buildAvatar(@value, "48px", true, "flex-shrink-0")} <div class="d-flex flex-column text-truncate"> <div class="fw-semibold text-truncate" title="{./displayname}">{./displayname}</div> <div class="text-xs text-muted text-truncate"> <span>{formattedNumber(./postcount)}!</span> </div> </div> </a> {{{ end }}} </div> </div> </div>
I created a widget in the Admin Panel:
Then finally, I get this:
Those 5 separate sections on the page, are the only things on /categories page that need data. I got the menu working, everything on that page is pulled in dynamically, except for the <sections></sections>
I will admit, I am pretty defeated.
-
@codenamejessica, no worries. When you are building a nodebb theme/plugin for the first time there is definitely a learning curve.
Looks like you got the widget working. The reason it's not showing any users is because you set the data to the field
posters
but your template is using{{{ each users }}}
-
Yeah, I thought I was supposed to install that!!! HAHA. See I have been just working on this for 18 hours per day for 7 straight days. Everything is blurring together at this point.
-
What debugging tools do you guys use? Obviously, I cannot use console.log(), and I cannot see any of the objects. So how am I supposed to get what is being sent?
-
You can use console.log and see output in the nodebb logs, vscode debugger also works and let's you step through code and see the data. Below is my launch.json file for vscode debugging.
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "NodeBB", "skipFiles": [ "${workspaceFolder}\\node_modules\\**\\*.js", "${workspaceFolder}\\src\\promisify.js", "<node_internals>/**" ], "program": "${workspaceFolder}\\app.js", "runtimeArgs": [ "--trace-warnings", "--stack-trace-limit=200" ] } ] }
If you are debugging a plugin/theme in node_modules folder remove the node_modules part from
skipFiles
-
I don't know what I am doing wrong. 33 hours just in the sidebar and I am not even closer than when I started. If I can just get 1 thing to work, I can figure out the rest. But nothing is working. Anybody wants to give it a go: https://www.github.com/girls-whocode/nodebb-theme-codename
Basically, I am trying to make it with the same modules as https://codenamejessica.com the dev site I am building this on is https://jbrowns.com