Beginner's Guide to Creating Discourse Plugins Part 2: Plugin Outlets

plugins

(Robin Ward) #1

Make sure you read the first part of the tutorial before this one, it will help a lot!

Getting Started: Handlebars Templates

Discourse’s client application is written using the Ember.js Javascript framework. Ember uses Handlebars for all HTML templates. There’s a great introduction to the templating language at that link, so definitely read it thoroughly.

The Problem: Adding elements to the Discourse User Interface

Many plugins need to add and extend the Discourse web interface. We provide a mechanism to do this called plugin outlets in handlebars templates.

If you browse the discourse handlebars templates, you’ll often see the following markup:

{{plugin-outlet name="edit-topic"}}

This is declaring a plugin outlet called “edit-topic”. It’s an extension point in the template that plugin authors can leverage to add their own handlebars markup.

When authoring your plugin, look in the discourse handlebars templates (in .hbs files) you want to change for a {{plugin-outlet}}. If there isn’t one, just ask us to extend it! We’ll happily add them if you have a good use case. If you want to make it easier and faster for us to do that, please submit a pull request on github!

If you want to see some of the places where plugin outlets exist, you can run the following command if you’re on OSX or Linux:

$ git grep "plugin-outlet" -- "*.hbs"

@Mittineague has also written a plugin to show their locations. I have to admit I have not tried it out myself so I’m not sure if it works, but it looks like it could be useful!

Connecting to a Plugin Outlet

Once you’ve found the plugin outlet you want to add to, you have to write a connector for it. A connector is really just a handlebars template whose filename includes connectors/<outlet name> in it.

For example, if your handlebars template has:

{{plugin-outlet name="evil-trout"}}

Then any handlebars files you create in the connectors/evil-trout directory
will automatically be appended. So if you created the file:

plugins/hello/assets/javascripts/discourse/templates/connectors/evil-trout/hello.hbs

With the contents:

<b>Hello World</b>

Discourse would insert <b>Hello World</b> at that point in the template.

Note that we called the file hello.hbs – The final part of the filename does not matter, but it must be unique across every plugin. It’s useful to name it something descriptive of what you are extending it to do. This will make debugging easier in the future.

Troubleshooting

  • Double check the name of the connector and make sure it matches the plugin name perfectly.

  • When in doubt, rm -rf tmp and start your development server again.

More in the series

Part 3: Site Settings


Beginner's Guide to Creating Discourse Plugins Part 3: Custom Settings
Beginner’s Guide to Creating Discourse Plugins Part 6: Acceptance Tests
Beginner's Guide to Creating Discourse Plugins - Part 1
Beginner's Guide to Creating Discourse Plugins Part 4: Git Setup
Problems adding custom button to discourse
Header Menu not showing in sequence
Custom User fields on Usercard
Allow reply-to individual instead of topic/forum (mailing list feature)
Moderation Plugin
Important changes to Plugin Outlets for Ember 2.10
Topic List Previews
Able to use the 'extraNavItem' custom html outlet?
Rails Girls 2015 SoC Banter
Beginner's Guide to Creating Discourse Plugins Part 5: Admin Interfaces
(Kenny Meyer) #2

Is there a list of plugin outlets?

More specifically I would like to know if one could modify the “create topic” template?


(cpradio) #3

In what way? Add new fields to the composer area (like the tagging plugin does)?


(Kenny Meyer) #4

Yes, that’s what I am searching for.


(Robin Ward) #5

I’d take a look at the tagging plugin then. It might have all you want!


(Andrew Byrne) #6

@eviltrout is there a way to output directly to JSON.
basically creating a new API endpoint?


(Andrew Byrne) #7

Ahhhhhhhh. new to this whole “ruby fad” :smiley:
I have a partial solution that i’ll detail in:


(Andrew Roth) #8

Hi Robin,

The plugin-outlet-locations plugin seems to declare all the connectors with a register_asset line in plugin.rb. Starting here: discourse-plugin-outlet-locations/plugin.rb at master · Mittineague/discourse-plugin-outlet-locations · GitHub

Is that a necessary step?


(Robin Ward) #9

Nope - that’s not necessary. All .es6 and .hbs files are loaded automatically in plugins.


(Ilias) #10

I am still trying to figure out how plugins in Discourse work and I could use a little help.

I would like to modify the timeline scroll bar (in the right side of each topic). Actually, what I need to do is add some stuff (image/banner) below the scroll bar.
What template should I edit? Is there an existing plugin-outlet for that?

Thank you,
Ilias


(Cheng Zheng) #11

2018-4-28 work for me!

1. Plugin Outlet name

2. Code

3. Result


(Sarah) #12

This guide is great! I had my plugin showing in the /admin/plugins quite easily.

I was wondering though, how do you delete items from a template?

For privacy reasons, I wanted to delete the export to csv button in the /admin/users/list/active as well as the show emails button. But I didn’t find a plugin outlet connector for those parts of the UI.

I was trying to overwrite the following templates

/users-list-show.hbs
/users-list.hbs

with my plugin outlet.

But creating these files
/var/www/discourse/plugins/[my-plugin]/assets/javascripts/admin/templates/users-list-show.hbs
/var/www/discourse/plugins/[my-plugin]/assets/javascripts/admin/templates/users-list.hbs
and making changes to them didnt seem to work. Even after deleting the /var/www/discourse/tmp folder and restarting the server.

Is this the correct way to delete those buttons from the UI? Using css display: none; isn’t an option.

I feel like I am missing something really simple, any ideas?


#13

Not a direct technical answer to your question but why would you want to do that?

Only the admins can do this. They usually have full control of the server most likely anyway and could read the database, so hiding a button is a bit futile: emails will also show up in the Email logs and on your mail service logs. I’m afraid site admins are going to see a lot of email addresses!

Admins have full control, they see everything (except passwords presumably), so this is normal.

If you are an admin, get used to the responsibility which comes with knowing all of this!


(Sarah) #14

My concern was that moderators can access some things in the admin dashboard.
They can navigate to the ‘users’ tab and see the Export and the Show Emails buttons
image

We don’t want our moderators to be able to grab bulk emails like this.
I understand that the emails are visible on users profiles, but we didn’t want an easy way to get this information.

So I was trying to create a plugin that hides these buttons.


#15

Could be wrong, but this suggests it’s not an issue … have you Impersonated a Mod?


(Sarah) #16

Yes, the screenshot I took was from impersonating a mod.

We have a similar setup as the link you provided (Moderators ability to see emails inconsistent).

I’m not requesting the Discourse team makes any changes though, this isn’t an issue with Discourse.

I am trying customize Discourse for our situation. I was hoping that using a plugin outlet and referencing the files within that plugin was the right way to overwrite a template in Discourse. I just wasn’t able to successfully overwrite these files:

/users-list-show.hbs
/users-list.hbs

My changes never showed up. So I thought this plugin outlet topic could help


#17

Perhaps someone else can chime in, but I’ve always seen Outlets as additive. You may need an override technique instead (via javascript/Ember). I’m still learning this myself :).


(Mittineague) #18

I’m thinking that if overriding a template is the goal that it might be better to do this with a theme instead of a plugin.


(Sarah) #19

I was thinking that as well, but I didn’t want a user to swap their theme and be able to get different functionality. So I figured a plugin outlet would do the trick


(Jay Pfaffman) #20

I think you can probably hide those with CSS.