1+ /* eslint-disable ember/no-classic-components, ember/require-tagless-components */
12import Component from " @ember/component" ;
23import { fn } from " @ember/helper" ;
34import { on } from " @ember/modifier" ;
@@ -17,16 +18,9 @@ import categoryLink, {
1718import icon from " discourse/helpers/d-icon" ;
1819import lazyHash from " discourse/helpers/lazy-hash" ;
1920import { slugify } from " discourse/lib/utilities" ;
20- import { i18n } from " discourse-i18n" ;
21+ import I18nInstance , { i18n } from " discourse-i18n" ;
2122import CategoryGroupExtraLink from " ./category-group-extra-link" ;
2223
23- function parseSettings (settings ) {
24- return settings .split (" |" ).map ((i ) => {
25- const [categoryGroup , categories ] = i .split (" :" ).map ((str ) => str .trim ());
26- return { categoryGroup, categories };
27- });
28- }
29-
3024const ExtraLink = class {
3125 constructor (args ) {
3226 this .isExtraLink = true ;
@@ -43,6 +37,14 @@ export default class CategoriesGroups extends Component {
4337 @service router;
4438 @service siteSettings;
4539
40+ localizedGroupName (group ) {
41+ const locale = I18nInstance .currentLocale ();
42+ const translation = (group .translations || []).find (
43+ (t ) => t .locale === locale
44+ );
45+ return translation? .name || group .name ;
46+ }
47+
4648 get shouldShow () {
4749 const currentRoute = this .router .currentRouteName ;
4850 const categoryPageStyle = this .siteSettings .desktop_category_page_style ;
@@ -63,41 +65,48 @@ export default class CategoriesGroups extends Component {
6365 }
6466
6567 get categoryGroupList () {
66- const parsedSettings = parseSettings ( settings .category_groups ) ;
67- const extraLinks = JSON . parse ( settings .extra_links || " [] " ) ;
68+ const parsedSettings = settings .category_groups ;
69+ const extraLinks = settings .extra_links || [] ;
6870
69- // Initialize an array to keep track of found categories and used links
71+ // Keep track of which categories landed in a group so the rest fall through
72+ // to the "ungrouped" section.
7073 const foundCategories = [];
71- const usedLinks = [];
7274
73- // Helper function to find extra link by ID
74- const findExtraLinkById = (id ) => extraLinks .find ((link ) => link .id === id);
75+ // Returns each category preceded by any extra links positioned before it
76+ // (via the link's `show_before` category), so links render inline next to a
77+ // category.
78+ const withLinks = (categories ) => {
79+ const items = [];
80+ categories .forEach ((category ) => {
81+ extraLinks
82+ .filter ((link ) => (link .show_before || []).includes (category .id ))
83+ .forEach ((link ) => items .push (new ExtraLink (link)));
84+ items .push (category);
85+ });
86+ return items;
87+ };
7588
7689 // Iterate through parsed settings in the defined order
7790 const categoryGroupList = parsedSettings .reduce ((groups , obj ) => {
78- const categoryArray = obj .categories .split (" ," ).map ((str ) => str .trim ());
79- const categoryGroup = [];
91+ const groupCategories = (obj .categories || [])
92+ .map ((id ) =>
93+ this .categories .find ((cat ) => cat .id === Number (id) && ! cat .hasMuted )
94+ )
95+ .filter (Boolean );
8096
81- // Iterate through each category/link in the order specified in settings
82- categoryArray .forEach ((categoryOrLinkId ) => {
83- const category = this .categories .find (
84- (cat ) => cat .slug === categoryOrLinkId && ! cat .hasMuted
85- );
97+ groupCategories .forEach ((c ) => foundCategories .push (c .slug ));
8698
87- if (category) {
88- categoryGroup .push (category);
89- foundCategories .push (category .slug );
90- } else {
91- const extraLink = findExtraLinkById (categoryOrLinkId);
92- if (extraLink) {
93- categoryGroup .push (new ExtraLink (extraLink));
94- usedLinks .push (extraLink .id );
95- }
96- }
97- });
99+ const items = withLinks (groupCategories);
98100
99- if (categoryGroup .length > 0 ) {
100- groups .push ({ name: obj .categoryGroup , items: categoryGroup });
101+ if (items .length > 0 ) {
102+ // `slug` is derived from the default name so it stays stable across
103+ // locales (used for CSS classes and localStorage collapse state),
104+ // while `name` is the localized label shown to the user.
105+ groups .push ({
106+ name: this .localizedGroupName (obj),
107+ slug: slugify (obj .name ),
108+ items,
109+ });
101110 }
102111 return groups;
103112 }, []);
@@ -115,25 +124,29 @@ export default class CategoriesGroups extends Component {
115124 if (settings .show_ungrouped && ungroupedCategories .length > 0 ) {
116125 categoryGroupList .push ({
117126 name: i18n (themePrefix (" ungrouped_categories_title" )),
118- items: ungroupedCategories,
127+ slug: " ungrouped" ,
128+ items: withLinks (ungroupedCategories),
119129 });
120130 }
121131
122132 if (mutedCategories .length > 0 ) {
123- categoryGroupList .push ({ name: " muted" , items: mutedCategories });
133+ categoryGroupList .push ({
134+ name: i18n (themePrefix (" muted_categories_title" )),
135+ slug: " muted" ,
136+ items: mutedCategories,
137+ });
124138 }
125139
126140 return categoryGroupList;
127141 }
128142
129143 @action
130- toggleCategories (name , event ) {
144+ toggleCategories (slug , event ) {
131145 event .preventDefault ();
132146
133- const id = slugify (name);
134147 const storedCategories =
135148 JSON .parse (localStorage .getItem (" categoryGroups" )) || [];
136- const categoryClass = ` .custom-category-group-${ id } ` ;
149+ const categoryClass = ` .custom-category-group-${ slug } ` ;
137150
138151 if (storedCategories .includes (categoryClass)) {
139152 storedCategories .removeObject (categoryClass);
@@ -161,11 +174,6 @@ export default class CategoriesGroups extends Component {
161174 });
162175 }
163176
164- @action
165- slugifyIdentifier (str ) {
166- return slugify (str);
167- }
168-
169177 <template >
170178 {{#if this . shouldShow }}
171179 <section class =" category-boxes with-logos with-subcategories" >
@@ -174,14 +182,11 @@ export default class CategoriesGroups extends Component {
174182 {{didInsert this . initializeLocalStorage}}
175183 >
176184 {{#each this . categoryGroupList as | t | }}
177- <div
178- class =" custom-category-group-{{this .slugifyIdentifier t.name }}
179- is-expanded"
180- >
185+ <div class =" custom-category-group-{{t.slug }} is-expanded" >
181186 <a
182- {{on " click" ( fn this . toggleCategories t.name ) }}
187+ {{on " click" ( fn this . toggleCategories t.slug ) }}
183188 href
184- id ={{this .slugifyIdentifier t.name }}
189+ id ={{t.slug }}
185190 class =" custom-category-group-toggle"
186191 >
187192 <h2 >{{t.name }} </h2 >
0 commit comments