FIX: Use plugin category name for plugin list (#24477)

Followup to e37fb3042d

Some plugins like discourse-ai and discourse-saml do not
nicely change from kebab-case to Title Case (e.g. Ai, Saml),
and anyway this method of getting the plugin name is not
translated either.

Better to use the plugin setting category if it exists,
since that is written by a human and is translated.
This commit is contained in:
Martin Brennan 2023-11-23 08:40:55 +10:00 committed by GitHub
parent 9f7c2d310a
commit e395e5e002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 25 deletions

View File

@ -28,9 +28,11 @@ export default class AdminPlugin {
this.authors = args.authors; this.authors = args.authors;
} }
get settingCategoryName() { get snakeCaseName() {
const snakeCaseName = this.name.replaceAll("-", "_"); return this.name.replaceAll("-", "_");
}
get translatedCategoryName() {
// We do this because the site setting list is grouped by category, // We do this because the site setting list is grouped by category,
// with plugins that have their root site setting key defined as `plugins:` // with plugins that have their root site setting key defined as `plugins:`
// being grouped under the generic "plugins" category. // being grouped under the generic "plugins" category.
@ -39,17 +41,26 @@ export default class AdminPlugin {
// we can use that instead to go directly to the setting category. // we can use that instead to go directly to the setting category.
// //
// Over time, no plugins should be missing this data. // Over time, no plugins should be missing this data.
const translationAttempt = I18n.lookup( return I18n.lookup(`admin.site_settings.categories.${this.snakeCaseName}`);
`admin.site_settings.categories.${snakeCaseName}` }
);
if (translationAttempt) { get settingCategoryName() {
return snakeCaseName; if (this.translatedCategoryName) {
return this.snakeCaseName;
} }
return "plugins"; return "plugins";
} }
get nameTitleized() { get nameTitleized() {
// The category name is better in a lot of cases, as it's a human-inputted
// translation, and we can handle things like SAML instead of showing them
// as Saml from discourse-saml. We can fall back to the programattic version
// though if needed.
if (this.translatedCategoryName) {
return this.translatedCategoryName;
}
return this.name return this.name
.split("-") .split("-")
.map((word) => { .map((word) => {

View File

@ -29,10 +29,15 @@
</div> </div>
</div> </div>
<div class="admin-nav pull-left"> <div class="admin-nav admin-site-settings-category-nav pull-left">
<ul class="nav nav-stacked"> <ul class="nav nav-stacked">
{{#each this.visibleSiteSettings as |category|}} {{#each this.visibleSiteSettings as |category|}}
<li class={{category.nameKey}}> <li
class={{concat-class
"admin-site-settings-category-nav__item"
category.nameKey
}}
>
<LinkTo <LinkTo
@route="adminSiteSettingsCategory" @route="adminSiteSettingsCategory"
@model={{category.nameKey}} @model={{category.nameKey}}

View File

@ -77,12 +77,14 @@ class Plugin::Instance
def self.find_all(parent_path) def self.find_all(parent_path)
[].tap do |plugins| [].tap do |plugins|
# also follows symlinks - http://stackoverflow.com/q/357754 # also follows symlinks - http://stackoverflow.com/q/357754
Dir["#{parent_path}/*/plugin.rb"].sort.each do |path| Dir["#{parent_path}/*/plugin.rb"].sort.each { |path| plugins << parse_from_source(path) }
end
end
def self.parse_from_source(path)
source = File.read(path) source = File.read(path)
metadata = Plugin::Metadata.parse(source) metadata = Plugin::Metadata.parse(source)
plugins << self.new(metadata, path) self.new(metadata, path)
end
end
end end
def initialize(metadata = nil, path = nil) def initialize(metadata = nil, path = nil)

View File

@ -3,30 +3,34 @@
describe "Admin Plugins List", type: :system, js: true do describe "Admin Plugins List", type: :system, js: true do
fab!(:current_user) { Fabricate(:admin) } fab!(:current_user) { Fabricate(:admin) }
before { sign_in(current_user) } before do
sign_in(current_user)
let(:spoiler_alert_plugin) do Discourse.stubs(:visible_plugins).returns([spoiler_alert_plugin])
plugins = Plugin::Instance.find_all("#{Rails.root}/plugins")
plugins.find { |p| p.name == "spoiler-alert" }
end end
xit "shows the list of plugins" do let(:spoiler_alert_plugin) do
path = File.join(Rails.root, "plugins", "spoiler-alert", "plugin.rb")
Plugin::Instance.parse_from_source(path)
end
it "shows the list of plugins" do
visit "/admin/plugins" visit "/admin/plugins"
plugin_row = find(".admin-plugins-list tr[data-plugin-name=\"spoiler-alert\"]") plugin_row =
find(".admin-plugins-list tr[data-plugin-name=\"spoiler-alert\"] td.admin-plugins-list__row")
expect(plugin_row).to have_css( expect(plugin_row).to have_css(
"td.admin-plugins-list__row .admin-plugins__name-with-badges .admin-plugins__name", ".admin-plugins-list__name-with-badges .admin-plugins-list__name",
text: "Spoiler Alert", text: "Spoiler Alert",
) )
expect(plugin_row).to have_css( expect(plugin_row).to have_css(
"td.admin-plugins-list__row .admin-plugins__author", ".admin-plugins-list__author",
text: I18n.t("admin_js.admin.plugins.author", { author: "Discourse" }), text: I18n.t("admin_js.admin.plugins.author", { author: "Discourse" }),
) )
expect(plugin_row).to have_css( expect(plugin_row).to have_css(
"td.admin-plugins-list__row .admin-plugins__name-with-badges .admin-plugins__name a[href=\"https://meta.discourse.org/t/12650\"]", ".admin-plugins-list__name-with-badges .admin-plugins-list__name a[href=\"https://meta.discourse.org/t/12650\"]",
) )
expect(plugin_row).to have_css( expect(plugin_row).to have_css(
"td.admin-plugins-list__row .admin-plugins__about", ".admin-plugins-list__about",
text: spoiler_alert_plugin.metadata.about, text: spoiler_alert_plugin.metadata.about,
) )
end end