Skip to content

Commit 69b43a2

Browse files
authored
Merge branch 'main' into main
2 parents 460b098 + 6419db2 commit 69b43a2

57 files changed

Lines changed: 894 additions & 521 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Create new d-compat branch
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "0 0 * * *"
7+
8+
jobs:
9+
ci:
10+
uses: discourse/.github/.github/workflows/create-d-compat-branch.yml@v1

Gemfile.lock

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ GEM
1414
securerandom (>= 0.3)
1515
tzinfo (~> 2.0, >= 2.0.5)
1616
uri (>= 0.13.1)
17+
addressable (2.8.9)
18+
public_suffix (>= 2.0.2, < 8.0)
1719
ast (2.4.3)
1820
base64 (0.3.0)
1921
bigdecimal (4.0.1)
@@ -22,34 +24,42 @@ GEM
2224
drb (2.2.3)
2325
i18n (1.14.8)
2426
concurrent-ruby (~> 1.0)
25-
json (2.18.0)
27+
json (2.19.1)
28+
json-schema (6.2.0)
29+
addressable (~> 2.8)
30+
bigdecimal (>= 3.1, < 5)
2631
language_server-protocol (3.17.0.5)
2732
lint_roller (1.1.0)
2833
logger (1.7.0)
29-
minitest (6.0.1)
34+
mcp (0.8.0)
35+
json-schema (>= 4.1)
36+
minitest (6.0.2)
37+
drb (~> 2.0)
3038
prism (~> 1.5)
3139
parallel (1.27.0)
32-
parser (3.3.10.1)
40+
parser (3.3.10.2)
3341
ast (~> 2.4.1)
3442
racc
3543
prettier_print (1.2.1)
36-
prism (1.8.0)
44+
prism (1.9.0)
45+
public_suffix (7.0.5)
3746
racc (1.8.1)
3847
rack (3.2.5)
3948
rainbow (3.1.1)
4049
regexp_parser (2.11.3)
41-
rubocop (1.84.0)
50+
rubocop (1.85.1)
4251
json (~> 2.3)
4352
language_server-protocol (~> 3.17.0.2)
4453
lint_roller (~> 1.1.0)
54+
mcp (~> 0.6)
4555
parallel (~> 1.10)
4656
parser (>= 3.3.0.2)
4757
rainbow (>= 2.2.2, < 4.0)
4858
regexp_parser (>= 2.9.3, < 3.0)
4959
rubocop-ast (>= 1.49.0, < 2.0)
5060
ruby-progressbar (~> 1.7)
5161
unicode-display_width (>= 2.4.0, < 4.0)
52-
rubocop-ast (1.49.0)
62+
rubocop-ast (1.49.1)
5363
parser (>= 3.3.7.2)
5464
prism (~> 1.7)
5565
rubocop-capybara (2.22.1)
@@ -102,4 +112,4 @@ DEPENDENCIES
102112
syntax_tree
103113

104114
BUNDLED WITH
105-
4.0.4
115+
4.0.8

javascripts/discourse/components/categories-groups.gjs

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
12
import Component from "@ember/component";
23
import { fn } from "@ember/helper";
34
import { on } from "@ember/modifier";
@@ -17,16 +18,9 @@ import categoryLink, {
1718
import icon from "discourse/helpers/d-icon";
1819
import lazyHash from "discourse/helpers/lazy-hash";
1920
import { slugify } from "discourse/lib/utilities";
20-
import { i18n } from "discourse-i18n";
21+
import I18nInstance, { i18n } from "discourse-i18n";
2122
import 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-
3024
const 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>

javascripts/discourse/connectors/above-discovery-categories/custom-categories-boxes.gjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
12
import Component from "@ember/component";
23
import { classNames } from "@ember-decorators/component";
3-
import { and, not, or } from "truth-helpers";
4+
import { and, or } from "discourse/truth-helpers";
45
import CategoriesGroups from "../../components/categories-groups";
56

67
@classNames("above-discovery-categories-outlet", "custom-categories-boxes")

locales/ar.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ ar:
88
theme_metadata:
99
description: "صفحة الفئة المخصَّصة مع إعدادات المجموعة"
1010
settings:
11-
category_groups: "التنسيق على النحو التالي: اسم المجموعة: category-slug، extra-link-id، category-slug-2"
12-
extra_links: "روابط إضافية يمكن دمجها في قائمة الفئات. أضِف معرِّف الرابط في إعداد category_groups لعرضه"
1311
show_on_mobile: "عرض مجموعات مربعات الفئات القابلة للطي على الجوَّال"
1412
show_ungrouped: "عرض مجموعة من الفئات التي لم يتم تعيينها إلى مجموعة أخرى"
1513
hide_muted_subcategories: "عند التفعيل، لن تظهر فئة رئيسية غير مكتومة أسفل القسم المكتوم إذا كانت تحتوي على فئة فرعية مكتومة"
1614
fancy_styling: "تشغيل التصميم الإضافي"
1715
ungrouped_categories_title: "أخرى"
16+
muted_categories_title: "المكتومة"

locales/be.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# https://translate.discourse.org/
66

77
be:
8+
muted_categories_title: "Без апавяшчэнняў"

locales/bg.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# https://translate.discourse.org/
66

77
bg:
8+
muted_categories_title: "Заглуши"

locales/bs_BA.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# https://translate.discourse.org/
66

77
bs_BA:
8+
muted_categories_title: "Utišani"

locales/ca.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# https://translate.discourse.org/
66

77
ca:
8+
muted_categories_title: "Silenciat"

locales/cs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# https://translate.discourse.org/
66

77
cs:
8+
muted_categories_title: "Ztišení"

0 commit comments

Comments
 (0)