开发 Discourse 插件 - 第 3 部分 - 添加自定义站点设置

上一篇教程:Developing Discourse Plugins - Part 2 - Connect to a plugin outlet


站点设置 (Site Settings)

如果您访问您拥有管理员权限的 Discourse 实例上的 /admin/site_settings,您会看到一个配置设置列表。开箱即用,我们提供了我们认为最适合 Discourse 安装的设置,但我们也理解人们希望调整他们的安装,以便让他们可以按照自己想要的方式设置论坛。

很有可能,除非您的插件非常简单,否则您会希望添加插件用户可以更改并用于配置功能的设置。幸运的是,这非常容易实现!

config/settings.yml

您需要做的第一件事是在您的插件文件夹中创建 config/settings.yml。此文件将概述您的插件所需的所有设置。这是一个示例文件:

plugins:
  awesomeness_enabled:
    default: true
    client: true
  awesomeness_max_volume:
    default: 10
    client: true

该文件需要采用 YAML 格式。YAML 可能非常挑剔,因此如果 Discourse 无法加载您的设置,我建议您尝试使用 YAMLint 等工具验证您的 YAML。

我将详细解释示例文件。顶层是 plugins,它告诉 Discourse 我们希望这些设置显示在站点设置的“插件 (Plugins)”下。

之后,声明了两个设置:awesomeness_enabledawesomeness_max_volume。Discourse 从默认值推断设置的类型,因此 awesomeness_enabled 是一个布尔值,而 awesomeness_max_volume 是一个数字。

client: true 这一点很重要。Discourse 由两个主要应用程序组成:用 Ruby on Rails 编写的服务器端 API 和用 Ember.js 编写的客户端应用程序。默认情况下,我们不会将设置暴露给 Ember.js 客户端应用程序,除非您添加 client: true。我们这样做是因为有些设置是私有的,例如 API 密钥,不应发送给最终用户。此外,如果我们向客户端发送所有设置,最终用户下载的内容可能会很多!

在我们的示例中,我们希望这两个设置在 JavaScript 世界以及服务器端世界中都可访问。

一个重要的第二步

在您可以使用新添加的站点设置之前,您需要为它们添加翻译。由于 Discourse 支持多种语言,您添加的任何文本都必须支持翻译成其他语言。

让我们用英语为我们的设置创建翻译:

config/locales/server.en.yml

en:
  site_settings:
    awesomeness_enabled: "Is this plugin awesome?"
    awesomeness_max_volume: "What is the maximum volume possible?"

我们在该文件中添加的标签将显示在管理区域中。最好尽可能清楚地说明设置的作用。

将设置声明为“启用设置”

现在我们有了站点设置,我们应该告诉 Discourse 这是打开和关闭我们功能的那个设置。

打开您的 plugin.rb 文件,并在元数据注释下方添加以下行:

enabled_site_setting :awesomeness_enabled

请确保您的所有其他设置都以 “awesomeness_” 开头,以便 /admin/plugins 处的设置按钮能够正常工作。

访问您的新设置

首先,您需要重新启动开发服务器以使设置生效。完成此操作后,这些设置应该可用于您的服务器端和客户端代码。

我们自动将站点设置注入到大多数 JavaScript 对象中,因此如果您正在声明 ComponentControllerRouteViewModel,您应该可以通过简单地使用 this.siteSettings.awesomeness_enabled 来访问站点设置。在大多数 Handlebars 模板中,您也应该能够说 {{siteSettings.awesomeness_enabled}},设置值就会显示出来。

我们尚未在此系列中介绍太多 Ruby 内容,但如果您想在 Ruby 应用程序中访问站点设置,可以通过以下方式实现:SiteSetting.awesomeness_enabled

现在,去为您的插件添加自定义设置吧!


系列中的更多内容

第 1 部分:插件基础知识
第 2 部分:插件插槽 (Plugin Outlets)
第 3 部分:本主题
第 4 部分:Git 设置
第 5 部分:管理界面
第 6 部分:验收测试
第 7 部分:发布您的插件


本文档已版本控制 - 在 GitHub 上 建议更改。

34 个赞

For those more familiar with YAML, this was probably obvious, and thanks to YAMLint that you referenced I was able to figure this out pretty quick, but I thought it was worth mentioning that the format for the config/locales/server.en.yml needs to specifically be:

en:
  site_settings:
    awesomeness_enabled: "Is this plugin awesome?"
    max_volume: "What is the maximum volume possible?"

Correct?

Another quick question, it’s great that I can get to the settings by clicking on the Change Settings button, but how do I get the plugin specific Settings button directly to the right of the plugin like the poll plugin?

https://s3.amazonaws.com/f.cl.ly/items/162n220f0M0P3e0j2U3M/Image%202015-07-29%20at%207.29.28%20PM.png

Or is that a little too much for a Beginner’s Guide?

4 个赞

I updated the guide to fix both of those :smile:

4 个赞

How do you get the settings button to pre-populate the search field like Discourse Tagging does? I feel like I’m missing something obvious.

Edit: Nevermind, I figured it out. You had to use *_enabled to get it to filter. I originally didn’t have an enabled setting because the URL was simply the factor for determining if it is enabled.

1 个赞

For some reason, {{siteSettings}} in the poster-name-right outlet returns undefined. I tested with other outlets and the return the expected value. I’m not sure why :sadpanda:

Had to work around it by using {{Discourse.SiteSettings}}

1 个赞

This isn’t working because the Post view code path is some of the oldest code we have and it doesn’t do all the automatic stuff newer code can do :frowning:

I’ve come up with a fix that I think will solve your problem:

In the future I’ll be able to remove this hack and it’ll just work.

3 个赞

Hey @eviltrout how can I add a user setting? I mean a setting for a plugin that every user can change on his profile? Can I set a default too?

I guess is the same as an Custom User Field, so can I create a new User Field from a plugin?

Unfortunately there’s no easy way to do this right now. There is probably a good argument to be made for such an API for plugin authors.

Until then the way to do it is to add the fields via plugin outlets to the user preferences, tap into serializers and saving logic to store the setting the PluginStore.

1 个赞

I ran into this a while back too. We have to expose the field in the site settings too. I’ll see if I can add a PR to make this easier.

1 个赞

For anyone following this tutorial and trying to get SiteSettings.awesomeness_enabled to return anything in a rails console, be aware that the tutorial is wrong. It should be SiteSetting.awesomeness_enabled (Setting without the s at the end!)

1 个赞

Hmmm, this works for me in the hbs files

{{#if siteSettings.plugin_outlet_locations_enabled}}

Different syntax depending on where it’s being called from?

EDIT
Ah, the singular - plural Rails “magic” thing.

Nope, your first guess was correct >.>

JS has Discourse.SiteSettings but Rails has SiteSetting.

3 个赞

Oops! Thanks for letting me know. I’ve updated the tutorial.

2 个赞

Well, I believe some infrastructure are not complete yet. But I am refurnishing old login plugins while it’s worthwhile to asking the future change to plugin infra. Shall I move settings from login to plugin prefix?

I would recommend to do that, yes.

1 个赞

Just to clarify, this is only the case if you say client: true, right?

Yes, that is correct. Javascript gets access to the “client side” site settings.

2 个赞

I do not completely understand this statement. I set it to client: false but it was still visible in admin settings. What exactly happens if you set client to false.

Thank you.

We ship up a big JSON object of all the site settings that have client: true to all users, so those are considered public and viewable.

If they don’t have client: true then they are meant to be available from the server side. The admin section is an exception - we need to return all site settings to admin users so they can be changed! It uses a different API to get them all.

9 个赞

Work for me! 2018-4-28

Code

config/settings.yml

config/locales/server.en.yml

plugin.rb

Result

http://localhost:3000/admin/site_settings/category/plugins


(oh, I saw the translation missing hint)

Thanks!

3 个赞