From a445e8cce58b683071d517f5ec52fa201585c09d Mon Sep 17 00:00:00 2001 From: Ted Johansson Date: Wed, 14 May 2025 09:44:25 +0800 Subject: [PATCH] DEV: Port the about page extra groups functionality into core (#32659) We want to merge the theme component that allows admins to display extra groups on the about page. The settings for this are now under About your site. All the code is lift-and-shift, with some minor adjustments, e.g. theme components can't use the group_list setting type, but it has been converted to that here. Also the system tests for the admin controls are new. This whole thing is gated behind a hidden site setting to avoid double rendering while we deprecate the theme component. --- .../about/extra-groups.gjs | 126 +++++++++++++++++ .../components/admin-config-areas/about.gjs | 41 ++++++ .../components/about-page-extra-groups.gjs | 129 ++++++++++++++++++ .../discourse/app/components/about-page.gjs | 12 ++ app/assets/stylesheets/common/base/about.scss | 30 ++++ .../admin/config/about_controller.rb | 13 ++ config/locales/client.en.yml | 9 ++ config/locales/server.en.yml | 4 + config/site_settings.yml | 23 ++++ spec/system/about_page_spec.rb | 36 +++++ spec/system/admin_about_config_area_spec.rb | 41 +++++- ...in_about_config_area_group_listing_card.rb | 39 ++++++ .../page_objects/components/form_kit.rb | 18 ++- spec/system/page_objects/pages/about.rb | 12 ++ .../pages/admin_about_config_area.rb | 4 + 15 files changed, 534 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/admin/addon/components/admin-config-area-cards/about/extra-groups.gjs create mode 100644 app/assets/javascripts/discourse/app/components/about-page-extra-groups.gjs create mode 100644 spec/system/page_objects/components/admin_about_config_area_group_listing_card.rb diff --git a/app/assets/javascripts/admin/addon/components/admin-config-area-cards/about/extra-groups.gjs b/app/assets/javascripts/admin/addon/components/admin-config-area-cards/about/extra-groups.gjs new file mode 100644 index 00000000000..c36398133a4 --- /dev/null +++ b/app/assets/javascripts/admin/addon/components/admin-config-area-cards/about/extra-groups.gjs @@ -0,0 +1,126 @@ +import Component from "@glimmer/component"; +import { cached } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import { service } from "@ember/service"; +import Form from "discourse/components/form"; +import { ajax } from "discourse/lib/ajax"; +import { popupAjaxError } from "discourse/lib/ajax-error"; +import { i18n } from "discourse-i18n"; +import GroupChooser from "select-kit/components/group-chooser"; + +export default class AdminConfigAreasAboutExtraGroups extends Component { + @service site; + @service toasts; + + @cached + get data() { + return { + aboutPageExtraGroups: + this.args.extraGroups.aboutPageExtraGroups.value + .split("|") + .map(Number) || [], + aboutPageExtraGroupsInitialMembers: + this.args.extraGroups.aboutPageExtraGroupsInitialMembers.value, + aboutPageExtraGroupsOrder: + this.args.extraGroups.aboutPageExtraGroupsOrder.value, + aboutPageExtraGroupsShowDescription: + this.args.extraGroups.aboutPageExtraGroupsShowDescription.value === + "true", + }; + } + + @action + async save(data) { + this.args.setGlobalSavingStatus(true); + try { + await ajax("/admin/config/about.json", { + type: "PUT", + data: { + extra_groups: { + groups: data.aboutPageExtraGroups.join("|"), + initial_members: data.aboutPageExtraGroupsInitialMembers, + order: data.aboutPageExtraGroupsOrder, + show_description: data.aboutPageExtraGroupsShowDescription, + }, + }, + }); + this.toasts.success({ + duration: 30000, + data: { + message: i18n("admin.config_areas.about.toasts.extra_groups_saved"), + }, + }); + } catch (err) { + popupAjaxError(err); + } finally { + this.args.setGlobalSavingStatus(false); + } + } + + get orderings() { + return this.args.extraGroups.aboutPageExtraGroupsOrder.choices; + } + + +} diff --git a/app/assets/javascripts/admin/addon/components/admin-config-areas/about.gjs b/app/assets/javascripts/admin/addon/components/admin-config-areas/about.gjs index 02be84f8da1..7254a6d7e7e 100644 --- a/app/assets/javascripts/admin/addon/components/admin-config-areas/about.gjs +++ b/app/assets/javascripts/admin/addon/components/admin-config-areas/about.gjs @@ -1,12 +1,16 @@ import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; import { action } from "@ember/object"; +import { service } from "@ember/service"; import AdminConfigAreaCard from "admin/components/admin-config-area-card"; import AdminConfigAreasAboutContactInformation from "admin/components/admin-config-area-cards/about/contact-information"; +import AdminConfigAreasAboutExtraGroups from "admin/components/admin-config-area-cards/about/extra-groups"; import AdminConfigAreasAboutGeneralSettings from "admin/components/admin-config-area-cards/about/general-settings"; import AdminConfigAreasAboutYourOrganization from "admin/components/admin-config-area-cards/about/your-organization"; export default class AdminConfigAreasAbout extends Component { + @service siteSettings; + @tracked saving = false; get generalSettings() { @@ -39,6 +43,27 @@ export default class AdminConfigAreasAbout extends Component { }; } + get extraGroups() { + return { + aboutPageExtraGroups: this.#lookupSettingFromData( + "about_page_extra_groups" + ), + aboutPageExtraGroupsInitialMembers: this.#lookupSettingFromData( + "about_page_extra_groups_initial_members" + ), + aboutPageExtraGroupsOrder: this.#lookupSettingFromData( + "about_page_extra_groups_order" + ), + aboutPageExtraGroupsShowDescription: this.#lookupSettingFromData( + "about_page_extra_groups_show_description" + ), + }; + } + + get showExtraGroups() { + return this.siteSettings.show_additional_about_groups === true; + } + @action setSavingStatus(status) { this.saving = status; @@ -91,6 +116,22 @@ export default class AdminConfigAreasAbout extends Component { /> + {{#if this.showExtraGroups}} + + <:content> + + + + {{/if}} diff --git a/app/assets/javascripts/discourse/app/components/about-page-extra-groups.gjs b/app/assets/javascripts/discourse/app/components/about-page-extra-groups.gjs new file mode 100644 index 00000000000..662445f1741 --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/about-page-extra-groups.gjs @@ -0,0 +1,129 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import { service } from "@ember/service"; +import { htmlSafe } from "@ember/template"; +import AboutPageUsers from "discourse/components/about-page-users"; +import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner"; +import { ajax } from "discourse/lib/ajax"; + +export default class AboutPageExtraGroups extends Component { + @service store; + @service site; + @service siteSettings; + + @tracked groups = []; + @tracked loading = false; + + constructor() { + super(...arguments); + this.loadGroups(); + } + + groupName(group) { + return group.full_name || group.name.replace(/[_-]/g, " "); + } + + @action + async loadGroups() { + this.loading = true; + try { + const groupsSetting = + this.siteSettings.about_page_extra_groups?.split("|").map(Number) || []; + + let groupsToFetch = this.site.groups.filter((group) => + groupsSetting.includes(group.id) + ); + + // ordered alphabetically by default + if ( + this.siteSettings.about_page_extra_groups_order === "order of creation" + ) { + groupsToFetch.sort((a, b) => a.id - b.id); + } + + const groupPromises = groupsToFetch.map(async (group) => { + try { + const groupDetails = await this.loadGroupDetails(group.name); + group.members = await this.loadGroupMembers(group.name); + Object.assign(group, groupDetails); + return group; + } catch (error) { + // eslint-disable-next-line no-console + console.error( + `Error loading members for group ${group.name}:`, + error + ); + return null; + } + }); + + const groupsWithMembers = (await Promise.all(groupPromises)).filter( + (group) => group && group.members.length > 0 + ); + + this.groups = groupsWithMembers; + } catch (error) { + // eslint-disable-next-line no-console + console.error("Error loading groups:", error); + this.groups = []; + } finally { + this.loading = false; + } + } + + async loadGroupDetails(groupName) { + try { + const response = await ajax(`/g/${groupName}`); + return response.group; + } catch (error) { + // eslint-disable-next-line no-console + console.error(`Error loading details for group ${groupName}:`, error); + return ""; + } + } + + async loadGroupMembers(groupName) { + try { + const response = await ajax(`/g/${groupName}/members?asc=true`); + return response.members || []; + } catch (error) { + // eslint-disable-next-line no-console + console.error(`Error loading members for group ${groupName}:`, error); + return []; + } + } + + get showGroupDescription() { + return this.siteSettings.about_page_extra_groups_show_description; + } + + get showInitialMembers() { + return this.siteSettings.about_page_extra_groups_initial_members; + } + + +} diff --git a/app/assets/javascripts/discourse/app/components/about-page.gjs b/app/assets/javascripts/discourse/app/components/about-page.gjs index 22bc68054da..bcbd56f3621 100644 --- a/app/assets/javascripts/discourse/app/components/about-page.gjs +++ b/app/assets/javascripts/discourse/app/components/about-page.gjs @@ -3,6 +3,8 @@ import { hash } from "@ember/helper"; import { LinkTo } from "@ember/routing"; import { service } from "@ember/service"; import { htmlSafe } from "@ember/template"; +import { isBlank } from "@ember/utils"; +import AboutPageExtraGroups from "discourse/components/about-page-extra-groups"; import AboutPageUsers from "discourse/components/about-page-users"; import PluginOutlet from "discourse/components/plugin-outlet"; import icon from "discourse/helpers/d-icon"; @@ -230,6 +232,13 @@ export default class AboutPage extends Component { return configs; } + get showExtraGroups() { + return ( + this.siteSettings.show_additional_about_groups === true && + !isBlank(this.siteSettings.about_page_extra_groups) + ); + } +