mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 13:09:18 +08:00
FEATURE: Show prompt for required tag groups (#16458)
This commit is contained in:
parent
42bb629817
commit
e5fb884695
|
@ -133,13 +133,26 @@ export function applyDefaultHandlers(pretender) {
|
|||
|
||||
pretender.delete("/bookmarks/:id", () => response({}));
|
||||
|
||||
pretender.get("/tags/filter/search", () => {
|
||||
return response({
|
||||
pretender.get("/tags/filter/search", (request) => {
|
||||
const responseBody = {
|
||||
results: [
|
||||
{ id: "monkey", name: "monkey", count: 1 },
|
||||
{ id: "gazelle", name: "gazelle", count: 2 },
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
if (
|
||||
request.queryParams.categoryId === "1" &&
|
||||
request.queryParams.q === "" &&
|
||||
!request.queryParams.selected_tags.includes("monkey")
|
||||
) {
|
||||
responseBody["required_tag_group"] = {
|
||||
name: "monkey group",
|
||||
min_count: 1,
|
||||
};
|
||||
}
|
||||
|
||||
return response(responseBody);
|
||||
});
|
||||
|
||||
pretender.get(`/u/:username/emails.json`, (request) => {
|
||||
|
|
|
@ -3,6 +3,7 @@ import componentTest, {
|
|||
} from "discourse/tests/helpers/component-test";
|
||||
import {
|
||||
discourseModule,
|
||||
query,
|
||||
queryAll,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import I18n from "I18n";
|
||||
|
@ -81,5 +82,34 @@ discourseModule(
|
|||
);
|
||||
},
|
||||
});
|
||||
|
||||
componentTest("required_tag_group", {
|
||||
template: hbs`{{mini-tag-chooser value=value options=(hash categoryId=1)}}`,
|
||||
|
||||
beforeEach() {
|
||||
this.set("value", ["foo", "bar"]);
|
||||
},
|
||||
|
||||
async test(assert) {
|
||||
assert.strictEqual(this.subject.header().value(), "foo,bar");
|
||||
|
||||
await this.subject.expand();
|
||||
|
||||
assert.strictEqual(
|
||||
query("input[name=filter-input-search]").placeholder,
|
||||
I18n.t("tagging.choose_for_topic_required_group", {
|
||||
count: 1,
|
||||
name: "monkey group",
|
||||
})
|
||||
);
|
||||
|
||||
await this.subject.selectRowByValue("monkey");
|
||||
|
||||
assert.strictEqual(
|
||||
query("input[name=filter-input-search]").placeholder,
|
||||
I18n.t("select_kit.filter_placeholder")
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -96,6 +96,18 @@ export default MultiSelectComponent.extend(TagsMixin, {
|
|||
results = results.sort((a, b) => a.text.localeCompare(b.text));
|
||||
}
|
||||
|
||||
if (json.required_tag_group) {
|
||||
context.set(
|
||||
"selectKit.options.translatedFilterPlaceholder",
|
||||
I18n.t("tagging.choose_for_topic_required_group", {
|
||||
count: json.required_tag_group.min_count,
|
||||
name: json.required_tag_group.name,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
context.set("selectKit.options.translatedFilterPlaceholder", null);
|
||||
}
|
||||
|
||||
return results.filter((r) => !makeArray(context.tags).includes(r.id));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -246,9 +246,10 @@ class TagsController < ::ApplicationController
|
|||
filter_params[:order_popularity] = true
|
||||
end
|
||||
|
||||
tags_with_counts = DiscourseTagging.filter_allowed_tags(
|
||||
tags_with_counts, filter_result_context = DiscourseTagging.filter_allowed_tags(
|
||||
guardian,
|
||||
filter_params
|
||||
**filter_params,
|
||||
with_context: true
|
||||
)
|
||||
|
||||
tags = self.class.tag_counts_json(tags_with_counts, show_pm_tags: guardian.can_tag_pms?)
|
||||
|
@ -281,6 +282,10 @@ class TagsController < ::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
if required_tag_group = filter_result_context[:required_tag_group]
|
||||
json_response[:required_tag_group] = required_tag_group
|
||||
end
|
||||
|
||||
render json: json_response
|
||||
end
|
||||
|
||||
|
|
|
@ -3836,6 +3836,9 @@ en:
|
|||
choose_for_topic_required:
|
||||
one: "select at least %{count} tag..."
|
||||
other: "select at least %{count} tags..."
|
||||
choose_for_topic_required_group:
|
||||
one: "select %{count} tag from '%{name}'..."
|
||||
other: "select %{count} tags from '%{name}'..."
|
||||
info: "Info"
|
||||
default_info: "This tag isn't restricted to any categories, and has no synonyms."
|
||||
staff_info: "To add restrictions, put this tag in a <a href=%{basePath}/tag_groups>tag group</a>."
|
||||
|
|
|
@ -367,11 +367,13 @@ module DiscourseTagging
|
|||
# - there are more available tags than the query limit
|
||||
# - and no search term has been included
|
||||
required_tag_ids = nil
|
||||
required_category_tag_group = nil
|
||||
if opts[:for_input] && category&.category_required_tag_groups.present? && (filter_for_non_staff || term.blank?)
|
||||
category.category_required_tag_groups.each do |crtg|
|
||||
group_tags = crtg.tag_group.tags.pluck(:id)
|
||||
next if (group_tags & selected_tag_ids).size >= crtg.min_count
|
||||
if filter_for_non_staff || group_tags.size >= opts[:limit].to_i
|
||||
required_category_tag_group = crtg
|
||||
required_tag_ids = group_tags
|
||||
builder.where("id IN (?)", required_tag_ids)
|
||||
end
|
||||
|
@ -441,6 +443,19 @@ module DiscourseTagging
|
|||
end
|
||||
|
||||
result = builder.query(builder_params).uniq { |t| t.id }
|
||||
|
||||
if opts[:with_context]
|
||||
context = {}
|
||||
if required_category_tag_group
|
||||
context[:required_tag_group] = {
|
||||
name: required_category_tag_group.tag_group.name,
|
||||
min_count: required_category_tag_group.min_count
|
||||
}
|
||||
end
|
||||
[result, context]
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def self.filter_visible(query, guardian = nil)
|
||||
|
|
|
@ -877,6 +877,28 @@ describe TagsController do
|
|||
expect(response.status).to eq(400)
|
||||
expect(response.parsed_body['errors'].first).to eq(I18n.t('invalid_params', message: 'limit'))
|
||||
end
|
||||
|
||||
it 'includes required tag group information' do
|
||||
tag1 = Fabricate(:tag)
|
||||
tag2 = Fabricate(:tag)
|
||||
|
||||
tag_group = Fabricate(:tag_group, tags: [tag1, tag2])
|
||||
crtg = CategoryRequiredTagGroup.new(tag_group: tag_group, min_count: 1)
|
||||
category = Fabricate(:category, category_required_tag_groups: [ crtg ])
|
||||
|
||||
get "/tags/filter/search.json", params: { q: '', categoryId: category.id, filterForInput: true }
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["results"].map { |t| t["name"] }).to contain_exactly(tag1.name, tag2.name)
|
||||
expect(response.parsed_body["required_tag_group"]).to eq({
|
||||
"name" => tag_group.name,
|
||||
"min_count" => crtg.min_count
|
||||
})
|
||||
|
||||
get "/tags/filter/search.json", params: { q: '', categoryId: category.id, filterForInput: true, selected_tags: [tag1.name] }
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["results"].map { |t| t["name"] }).to contain_exactly(tag2.name)
|
||||
expect(response.parsed_body["required_tag_group"]).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user