how modify user profle page with a response in a plugin


  • GNU/Linux

    Suppose to have a plugin and this plugin, in according a one result, must modify the standard profile page of nodebb. I don't know how I can do this I try to attack at some <div> in the page but I don't have obtain a good result. Anyone can help me?


  • Community Rep

    Adding new divs and things can be difficult, because you can't be sure of the specific theme the forum is using. The best way to add custom profile information is to create a custom route using a custom template with the information you want, and then add a link to that page into the user profile page using the filter:user.profileLinks hook. This adds a link with an icon to the dropdown in the user's profile page. In the custom template you are making, you can make it look like part of the profile page by using <!-- IMPORT partials/account/header.tpl --> near the start of your template.

    The object structure for the hook looks like this:

    Plugin.profileLinks = function (links, next) {
    	links.push({
    		id: 'minecraft',	// This is the html id added for styling with css.
    		public: true,		// Set this to false and the link will only
    							// appear if the user is viewing their own profile.
    		route: 'minecraft',	// Added to the route below.
    		icon: 'fa-cube',	// FontAwesome icon displayed next to the link.
    		name: 'Minecraft Profile' // Text displayed for the link.
    	});
    	next(null, links);
    };
    

    Your custom routes should look similar to this:

    router.get('/api/user/:user/minecraft', renderMinecraftProfile);
    router.get('/user/:user/minecraft', NodeBB.middleware.buildHeader, renderMinecraftProfile);
    

    This is the best way to add information to the profile page since it will work flawlessly(TM) with any theme.

    If you actually want to change the main profile page using a plugin, there's two basic ways I know of.

    On the client, using jQuery. Or on the server, by directly appending the template file and using the filter:user.account hook.

    Use jQuery by adding the ajaxify hook to your client script, checking that the right page has loaded.

    $(function(){
      $(window).on('action:ajaxify.contentLoaded', function(event, data) {
        if (data.tpl === "account/profile") {
           // Add your jQuery here.
           $('.account-stats').after('<div class="cool">Your cool new div.</div>');
           // You could get variables here by calling a socket method.
        }
      });
    });
    

    If you're having difficulty in making jQuery insert data where you want it, there are many good tutorials, and the jQuery docs are quite robust.

    Another more risky way to add data is by manually modifying the template. I use this method in my minecraft plugin, and I actually copied it from another plugin I can't remeber the name of. It works good for any information that you only need to get once per page load, since it renders all the information before the page gets to the browser, and you don't have to mess with socket calls to add data.

    In your plugins library file, (in the gloabl scope, not in your init function) I call the emitter like this.

    var fs = require('fs');
    var path = require('path');
    var nconf = require.main.require('nconf');
    var emitter = require.main.require('./src/emitter');
    
    emitter.once('nodebb:ready', function (callback) {
    	callback = callback || function() {};
    
    	var	tplPath = path.join(nconf.get('base_dir'), 'public/templates/account/profile.tpl');
    
    	fs.readFile(tplPath, function(err, tpl) {
    		if (err) { return callback(err); }
    
    		tpl = tpl.toString();
    
    		if (!tpl.match('{prefix}'))
    		{
    			if (tpl.match('<!-- IF fullname -->{fullname}<!-- ELSE -->{username}<!-- ENDIF fullname -->')) {
    				// Persona
    				tpl = tpl.replace('<!-- IF fullname -->{fullname}<!-- ELSE -->{username}<!-- ENDIF fullname -->', '{prefix}');
    			}else{
    				// Vanilla/Lavender
    				tpl = tpl.replace('<i component="user/status" class="fa fa-circle status {status}" title="[[global:{status}]]"></i>', '<span class="h4">{prefix}</span><br><i component="user/status" class="fa fa-circle status {status}" title="[[global:{status}]]"></i>');
    			}
    		}
    
    		fs.writeFile(tplPath, tpl, callback);
    	});
    });
    

    I add the variable {prefix} in the filter:user.account hook.

    Plugin.userAccount = function (data, callback) {
    	getPrefix(data.userData.uid, function (err, prefix) {
    		data.userData.prefix = prefix || "";
    		callback(null, data);
    	});
    }
    

    This works fantastic for me, but as you can tell, it's super-dependent on specific themes.

    Hope that helps.


  • Plugin & Theme Dev

    @yariplus said:

    if (data.tpl_url === "account/profile") {

    small correction... it's data.tpl not data.tpl_url


  • Community Rep

    @pichalite Ah, you're right. Looks like tpl_url was added in master. Changed the hook to contentLoaded, since end doesn't pass the template in 0.9.x.




Looks like your connection to NodeBB was lost, please wait while we try to reconnect.