mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 12:05:31 +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
|
@ -135,10 +135,10 @@ export function defaultCategoryLinkRenderer(category, opts) {
|
|||
dataAttributes += ` data-parent-category-id="${parentCat.id}"`;
|
||||
}
|
||||
|
||||
html += `<span
|
||||
${dataAttributes}
|
||||
data-drop-close="true"
|
||||
class="${classNames}"
|
||||
html += `<span
|
||||
${dataAttributes}
|
||||
data-drop-close="true"
|
||||
class="${classNames}"
|
||||
${
|
||||
opts.previewColor
|
||||
? `style="--category-badge-color: #${category.color}"`
|
||||
|
@ -169,6 +169,13 @@ export function defaultCategoryLinkRenderer(category, opts) {
|
|||
html += buildTopicCount(opts.topicCount);
|
||||
}
|
||||
|
||||
if (opts.subcategoryCount) {
|
||||
html += `<span class="plus-subcategories">${I18n.t(
|
||||
"category_row.subcategory_count",
|
||||
{ count: opts.subcategoryCount }
|
||||
)}</span>`;
|
||||
}
|
||||
|
||||
if (href) {
|
||||
href = ` href="${href}" `;
|
||||
}
|
||||
|
|
|
@ -464,6 +464,17 @@ export default class Category extends RestModel {
|
|||
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")
|
||||
level(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() {
|
||||
return this.args.item?.name;
|
||||
return this.args.item?.name || this.args.item?.label;
|
||||
}
|
||||
|
||||
get displayCategoryDescription() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { computed } from "@ember/object";
|
||||
import EmberObject, { computed } from "@ember/object";
|
||||
import { mapBy } from "@ember/object/computed";
|
||||
import { categoryBadgeHTML } from "discourse/helpers/category-link";
|
||||
import Category from "discourse/models/category";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
import CategoryRow from "select-kit/components/category-row";
|
||||
|
@ -51,34 +52,51 @@ export default MultiSelectComponent.extend({
|
|||
},
|
||||
|
||||
async search(filter) {
|
||||
if (!this.site.lazy_load_categories) {
|
||||
return this._super(filter);
|
||||
let categories;
|
||||
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([
|
||||
...this.categories.map((c) => c.id),
|
||||
...this.blockedCategories.map((c) => c.id),
|
||||
]);
|
||||
// If there is a single match and it has subcategories, add a row for
|
||||
// selecting all
|
||||
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, {
|
||||
includeUncategorized:
|
||||
this.options?.allowUncategorized !== undefined
|
||||
? this.options.allowUncategorized
|
||||
: this.selectKit.options.allowUncategorized,
|
||||
rejectCategoryIds: Array.from(rejectCategoryIds),
|
||||
});
|
||||
return categories;
|
||||
},
|
||||
|
||||
select(value, item) {
|
||||
if (item.multiCategory) {
|
||||
const items = item.multiCategory.map((id) =>
|
||||
Category.findById(parseInt(id, 10))
|
||||
if (item.categories) {
|
||||
this.selectKit.change(
|
||||
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 {
|
||||
this._super(value, item);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
.topic-count {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.plus-subcategories {
|
||||
font-size: var(--font-down-2);
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-choice-category {
|
||||
|
|
|
@ -2340,6 +2340,9 @@ en:
|
|||
loading: Loading…
|
||||
|
||||
category_row:
|
||||
subcategory_count:
|
||||
one: "+ %{count} subcategory"
|
||||
other: "+ %{count} subcategories"
|
||||
topic_count:
|
||||
one: "%{count} topic in this category"
|
||||
other: "%{count} topics in this category"
|
||||
|
|
Loading…
Reference in New Issue
Block a user