diff --git a/app/assets/javascripts/admin/addon/controllers/admin-plugins.js b/app/assets/javascripts/admin/addon/controllers/admin-plugins.js index be663cadb15..34ffe45783d 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-plugins.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-plugins.js @@ -1,17 +1,27 @@ import { action } from "@ember/object"; import Controller from "@ember/controller"; -import discourseComputed from "discourse-common/utils/decorators"; +import { inject as service } from "@ember/service"; export default Controller.extend({ - @discourseComputed - adminRoutes() { + router: service(), + + get adminRoutes() { + return this.allAdminRoutes.filter((r) => this.routeExists(r.full_location)); + }, + + get brokenAdminRoutes() { + return this.allAdminRoutes.filter( + (r) => !this.routeExists(r.full_location) + ); + }, + + get allAdminRoutes() { return this.model + .filter((p) => p?.enabled) .map((p) => { - if (p.get("enabled")) { - return p.admin_route; - } + return p.admin_route; }) - .compact(); + .filter(Boolean); }, @action @@ -21,4 +31,13 @@ export default Controller.extend({ adminDetail.classList.toggle(state); }); }, + + routeExists(routeName) { + try { + this.router.urlFor(routeName); + return true; + } catch (e) { + return false; + } + }, }); diff --git a/app/assets/javascripts/admin/addon/templates/plugins.hbs b/app/assets/javascripts/admin/addon/templates/plugins.hbs index 1425cf479ef..1baaaddd2d7 100644 --- a/app/assets/javascripts/admin/addon/templates/plugins.hbs +++ b/app/assets/javascripts/admin/addon/templates/plugins.hbs @@ -19,5 +19,11 @@
+ {{#each this.brokenAdminRoutes as |route|}} +
+ {{i18n "admin.plugins.broken_route" name=(i18n route.label)}} +
+ {{/each}} + {{outlet}}
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-plugins-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-plugins-test.js new file mode 100644 index 00000000000..61ca9fafc3c --- /dev/null +++ b/app/assets/javascripts/discourse/tests/acceptance/admin-plugins-test.js @@ -0,0 +1,51 @@ +import { + acceptance, + exists, + query, +} from "discourse/tests/helpers/qunit-helpers"; +import { visit } from "@ember/test-helpers"; +import { test } from "qunit"; + +acceptance("Admin - Plugins", function (needs) { + needs.user(); + + needs.pretender((server, helper) => { + server.get("/admin/plugins", () => + helper.response({ + plugins: [ + { + id: "some-test-plugin", + name: "some-test-plugin", + about: "Plugin description", + version: "0.1", + url: "https://example.com", + admin_route: { + location: "testlocation", + label: "test.plugin.label", + full_location: "adminPlugins.testlocation", + }, + enabled: true, + enabled_setting: "testplugin_enabled", + has_settings: true, + is_official: true, + }, + ], + }) + ); + }); + + test("shows plugin list", async function (assert) { + await visit("/admin/plugins"); + const table = query("table.admin-plugins"); + assert.strictEqual( + table.querySelector("tr .plugin-name .name").innerText, + "some-test-plugin", + "displays the plugin in the table" + ); + + assert.true( + exists(".admin-plugins .admin-detail .alert-error"), + "displays an error for unknown routes" + ); + }); +}); diff --git a/app/assets/stylesheets/testem.scss b/app/assets/stylesheets/testem.scss index cb117a88252..a1e4c5dad37 100644 --- a/app/assets/stylesheets/testem.scss +++ b/app/assets/stylesheets/testem.scss @@ -19,6 +19,7 @@ $love: #fa6c8d !default; @import "common/foundation/mixins"; @import "desktop"; @import "color_definitions"; +@import "admin"; #ember-testing-container { box-sizing: border-box; diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index fb29c37f874..0cc78869985 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -4639,6 +4639,7 @@ en: change_settings_short: "Settings" howto: "How do I install plugins?" official: "Official Plugin" + broken_route: "Unable to configure link to '%{name}'. Ensure ad-blockers are disabled and try reloading the page." backups: title: "Backups"