From 0bb86129a585ee56481294e615189e1ccb01b74b Mon Sep 17 00:00:00 2001 From: Krzysztof Kotlarek Date: Fri, 5 Jan 2024 12:15:16 +1100 Subject: [PATCH] FEATURE: used, unused, enabled, disabled component filter (#25136) In this PR we introduced the enabled/disabled components filter. https://github.com/discourse/discourse/pull/25105 However, components are slightly more complicated and can be used/unused/enabled/disabled. --- .../admin/addon/components/themes-list.js | 39 +++++-- .../components/themes-list-test.js | 107 ++++++++++++++++++ config/locales/client.en.yml | 2 + 3 files changed, 140 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/admin/addon/components/themes-list.js b/app/assets/javascripts/admin/addon/components/themes-list.js index 8bf160175b5..76ac06b45a8 100644 --- a/app/assets/javascripts/admin/addon/components/themes-list.js +++ b/app/assets/javascripts/admin/addon/components/themes-list.js @@ -11,6 +11,8 @@ import { COMPONENTS, THEMES } from "admin/models/theme"; const ALL_FILTER = "all"; const ACTIVE_FILTER = "active"; const INACTIVE_FILTER = "inactive"; +const ENABLED_FILTER = "enabled"; +const DISABLED_FILTER = "disabled"; const UPDATES_AVAILABLE_FILTER = "updates_available"; const THEMES_FILTERS = [ @@ -28,13 +30,21 @@ const THEMES_FILTERS = [ const COMPONENTS_FILTERS = [ { name: I18n.t("admin.customize.component.all_filter"), id: ALL_FILTER }, { - name: I18n.t("admin.customize.component.enabled_filter"), + name: I18n.t("admin.customize.component.used_filter"), id: ACTIVE_FILTER, }, { - name: I18n.t("admin.customize.component.disabled_filter"), + name: I18n.t("admin.customize.component.unused_filter"), id: INACTIVE_FILTER, }, + { + name: I18n.t("admin.customize.component.enabled_filter"), + id: ENABLED_FILTER, + }, + { + name: I18n.t("admin.customize.component.disabled_filter"), + id: DISABLED_FILTER, + }, { name: I18n.t("admin.customize.component.updates_available_filter"), id: UPDATES_AVAILABLE_FILTER, @@ -105,9 +115,7 @@ export default class ThemesList extends Component { (theme) => !theme.get("user_selectable") && !theme.get("default") ); } - if (this.filter === UPDATES_AVAILABLE_FILTER) { - results = results.filterBy("isPendingUpdates"); - } + results = this._applyFilter(results); return this._searchThemes(results, this.searchTerm); } @@ -148,9 +156,7 @@ export default class ThemesList extends Component { .localeCompare(b.get("name").toLowerCase()); }); } - if (this.filter === UPDATES_AVAILABLE_FILTER) { - results = results.filterBy("isPendingUpdates"); - } + results = this._applyFilter(results); return this._searchThemes(results, this.searchTerm); } @discourseComputed("themesList.@each.markedToDelete") @@ -174,6 +180,23 @@ export default class ThemesList extends Component { return themes.filter(({ name }) => name.toLowerCase().includes(term)); } + _applyFilter(results) { + switch (this.filter) { + case UPDATES_AVAILABLE_FILTER: { + return results.filterBy("isPendingUpdates"); + } + case ENABLED_FILTER: { + return results.filterBy("enabled"); + } + case DISABLED_FILTER: { + return results.filterBy("enabled", false); + } + default: { + return results; + } + } + } + @bind toggleInactiveMode(event) { event?.preventDefault(); diff --git a/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js index 1a3353c01aa..31442cf5a4a 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js @@ -263,6 +263,113 @@ module("Integration | Component | themes-list", function (hooks) { ); }); + test("components filter", async function (assert) { + const components = [ + Theme.create({ + name: "Component used 1", + component: true, + user_selectable: true, + parent_themes: [1], + enabled: true, + }), + Theme.create({ + name: "Component used 2", + component: true, + user_selectable: true, + parent_themes: [1], + enabled: true, + }), + Theme.create({ + name: "Component unused 1", + component: true, + user_selectable: false, + parent_themes: [], + enabled: true, + }), + Theme.create({ + name: "Component unused and disabled 1", + component: true, + user_selectable: false, + parent_themes: [], + enabled: false, + remote_theme: { + id: 42, + remote_url: + "git@github.com:discourse-org/discourse-incomplete-theme.git", + commits_behind: 1, + }, + }), + ]; + this.setProperties({ + components, + currentTab: COMPONENTS, + }); + + await render( + hbs`` + ); + + assert.ok(exists(".themes-list-filter__input")); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + [ + "Component used 1", + "Component used 2", + "Component unused 1", + "Component unused and disabled 1", + ] + ); + + await selectKit(".themes-list-filter__input").expand(); + await selectKit(".themes-list-filter__input").selectRowByValue("active"); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + ["Component used 1", "Component used 2"] + ); + + await selectKit(".themes-list-filter__input").expand(); + await selectKit(".themes-list-filter__input").selectRowByValue("inactive"); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + ["Component unused 1", "Component unused and disabled 1"] + ); + + await selectKit(".themes-list-filter__input").expand(); + await selectKit(".themes-list-filter__input").selectRowByValue("enabled"); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + ["Component used 1", "Component used 2", "Component unused 1"] + ); + + await selectKit(".themes-list-filter__input").expand(); + await selectKit(".themes-list-filter__input").selectRowByValue("disabled"); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + ["Component unused and disabled 1"] + ); + + await selectKit(".themes-list-filter__input").expand(); + await selectKit(".themes-list-filter__input").selectRowByValue( + "updates_available" + ); + assert.deepEqual( + [...queryAll(".themes-list-container__item .info .name")].map((node) => + node.textContent.trim() + ), + ["Component unused and disabled 1"] + ); + }); + test("switching between themes and components tabs keeps the search visible only if both tabs have at least 10 items", async function (assert) { const themes = createThemes(10, (n) => { return { name: `Theme ${n}${n}` }; diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 5c9589d7c69..f13f692ee6a 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -5280,6 +5280,8 @@ en: revert_confirm: "Are you sure you want to revert your changes?" component: all_filter: "All" + used_filter: "Used" + unused_filter: "Unused" enabled_filter: "Enabled" disabled_filter: "Disabled" updates_available_filter: "Updates Available"