mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 16:35:43 +08:00
FEATURE: Add "+ subcategories" option back (#26035)
This option was introduced at some point in the past, but was removed
during the work necessary to make Discourse work with a large number of
categories.
Follow up to commit 2e68ead45b
.
This commit is contained in:
parent
99b6068ede
commit
8dbcfef3fd
|
@ -169,6 +169,13 @@ export function defaultCategoryLinkRenderer(category, opts) {
|
||||||
html += buildTopicCount(opts.topicCount);
|
html += buildTopicCount(opts.topicCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts.subcategoryCount) {
|
||||||
|
html += `<span class="plus-subcategories">${I18n.t(
|
||||||
|
"category_row.subcategory_count",
|
||||||
|
{ count: opts.subcategoryCount }
|
||||||
|
)}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
href = ` href="${href}" `;
|
href = ` href="${href}" `;
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,6 +464,17 @@ export default class Category extends RestModel {
|
||||||
return [...(parentAncestors || []), this];
|
return [...(parentAncestors || []), this];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@discourseComputed("subcategories")
|
||||||
|
descendants() {
|
||||||
|
const descendants = [this];
|
||||||
|
for (let i = 0; i < descendants.length; i++) {
|
||||||
|
if (descendants[i].subcategories) {
|
||||||
|
descendants.push(...descendants[i].subcategories);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return descendants;
|
||||||
|
}
|
||||||
|
|
||||||
@discourseComputed("parentCategory.level")
|
@discourseComputed("parentCategory.level")
|
||||||
level(parentLevel) {
|
level(parentLevel) {
|
||||||
if (!parentLevel) {
|
if (!parentLevel) {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { render } from "@ember/test-helpers";
|
||||||
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
|
import { module, test } from "qunit";
|
||||||
|
import Category from "discourse/models/category";
|
||||||
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
|
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||||
|
|
||||||
|
module(
|
||||||
|
"Integration | Component | select-kit/category-selector",
|
||||||
|
function (hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
hooks.beforeEach(function () {
|
||||||
|
this.set("subject", selectKit());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with value", async function (assert) {
|
||||||
|
const category = Category.findById(1001);
|
||||||
|
const subcategory = Category.findById(1002);
|
||||||
|
this.set("value", [category, subcategory]);
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<CategorySelector
|
||||||
|
@categories={{this.value}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.strictEqual(this.subject.header().value(), "1001,1002");
|
||||||
|
assert.strictEqual(
|
||||||
|
this.subject.header().label(),
|
||||||
|
"Parent Category, Sub Category"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("has +subcategories row", async function (assert) {
|
||||||
|
this.set("value", []);
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<CategorySelector
|
||||||
|
@categories={{this.value}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
await this.subject.expand();
|
||||||
|
await this.subject.fillInFilter("Parent Category");
|
||||||
|
|
||||||
|
assert.equal(this.subject.rows().length, 2);
|
||||||
|
assert.equal(
|
||||||
|
this.subject.rowByIndex(0).el().innerText.replace("\n", " "),
|
||||||
|
"Parent Category × 95"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.subject.rowByIndex(1).el().innerText.replace("\n", " "),
|
||||||
|
"Parent Category + 2 subcategories"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
|
@ -64,7 +64,7 @@ export default class CategoryRow extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
get label() {
|
get label() {
|
||||||
return this.args.item?.name;
|
return this.args.item?.name || this.args.item?.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
get displayCategoryDescription() {
|
get displayCategoryDescription() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { computed } from "@ember/object";
|
import EmberObject, { computed } from "@ember/object";
|
||||||
import { mapBy } from "@ember/object/computed";
|
import { mapBy } from "@ember/object/computed";
|
||||||
|
import { categoryBadgeHTML } from "discourse/helpers/category-link";
|
||||||
import Category from "discourse/models/category";
|
import Category from "discourse/models/category";
|
||||||
import { makeArray } from "discourse-common/lib/helpers";
|
import { makeArray } from "discourse-common/lib/helpers";
|
||||||
import CategoryRow from "select-kit/components/category-row";
|
import CategoryRow from "select-kit/components/category-row";
|
||||||
|
@ -51,34 +52,51 @@ export default MultiSelectComponent.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
async search(filter) {
|
async search(filter) {
|
||||||
if (!this.site.lazy_load_categories) {
|
let categories;
|
||||||
return this._super(filter);
|
if (this.site.lazy_load_categories) {
|
||||||
|
const rejectCategoryIds = new Set([
|
||||||
|
...this.categories.map((c) => c.id),
|
||||||
|
...this.blockedCategories.map((c) => c.id),
|
||||||
|
]);
|
||||||
|
|
||||||
|
categories = await Category.asyncSearch(filter, {
|
||||||
|
includeUncategorized:
|
||||||
|
this.options?.allowUncategorized !== undefined
|
||||||
|
? this.options.allowUncategorized
|
||||||
|
: this.selectKit.options.allowUncategorized,
|
||||||
|
rejectCategoryIds: Array.from(rejectCategoryIds),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
categories = this._super(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rejectCategoryIds = new Set([
|
// If there is a single match and it has subcategories, add a row for
|
||||||
...this.categories.map((c) => c.id),
|
// selecting all
|
||||||
...this.blockedCategories.map((c) => c.id),
|
if (categories.length === 1) {
|
||||||
]);
|
const descendants = categories[0].descendants;
|
||||||
|
if (descendants.length > 1) {
|
||||||
|
categories.push(
|
||||||
|
EmberObject.create({
|
||||||
|
label: categoryBadgeHTML(descendants[0], {
|
||||||
|
link: false,
|
||||||
|
recursive: true,
|
||||||
|
subcategoryCount: descendants.length - 1,
|
||||||
|
}),
|
||||||
|
categories: [...descendants],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await Category.asyncSearch(filter, {
|
return categories;
|
||||||
includeUncategorized:
|
|
||||||
this.options?.allowUncategorized !== undefined
|
|
||||||
? this.options.allowUncategorized
|
|
||||||
: this.selectKit.options.allowUncategorized,
|
|
||||||
rejectCategoryIds: Array.from(rejectCategoryIds),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
select(value, item) {
|
select(value, item) {
|
||||||
if (item.multiCategory) {
|
if (item.categories) {
|
||||||
const items = item.multiCategory.map((id) =>
|
this.selectKit.change(
|
||||||
Category.findById(parseInt(id, 10))
|
makeArray(this.value).concat(item.categories.mapBy("id")),
|
||||||
|
makeArray(this.selectedContent).concat(item.categories)
|
||||||
);
|
);
|
||||||
|
|
||||||
const newValues = makeArray(this.value).concat(items.map((i) => i.id));
|
|
||||||
const newContent = makeArray(this.selectedContent).concat(items);
|
|
||||||
|
|
||||||
this.selectKit.change(newValues, newContent);
|
|
||||||
} else {
|
} else {
|
||||||
this._super(value, item);
|
this._super(value, item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
.topic-count {
|
.topic-count {
|
||||||
margin-left: 0.25em;
|
margin-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plus-subcategories {
|
||||||
|
font-size: var(--font-down-2);
|
||||||
|
margin-left: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-choice-category {
|
.selected-choice-category {
|
||||||
|
|
|
@ -2340,6 +2340,9 @@ en:
|
||||||
loading: Loading…
|
loading: Loading…
|
||||||
|
|
||||||
category_row:
|
category_row:
|
||||||
|
subcategory_count:
|
||||||
|
one: "+ %{count} subcategory"
|
||||||
|
other: "+ %{count} subcategories"
|
||||||
topic_count:
|
topic_count:
|
||||||
one: "%{count} topic in this category"
|
one: "%{count} topic in this category"
|
||||||
other: "%{count} topics in this category"
|
other: "%{count} topics in this category"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user