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.delete("/bookmarks/:id", () => response({}));
|
||||||
|
|
||||||
pretender.get("/tags/filter/search", () => {
|
pretender.get("/tags/filter/search", (request) => {
|
||||||
return response({
|
const responseBody = {
|
||||||
results: [
|
results: [
|
||||||
{ id: "monkey", name: "monkey", count: 1 },
|
{ id: "monkey", name: "monkey", count: 1 },
|
||||||
{ id: "gazelle", name: "gazelle", count: 2 },
|
{ 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) => {
|
pretender.get(`/u/:username/emails.json`, (request) => {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import componentTest, {
|
||||||
} from "discourse/tests/helpers/component-test";
|
} from "discourse/tests/helpers/component-test";
|
||||||
import {
|
import {
|
||||||
discourseModule,
|
discourseModule,
|
||||||
|
query,
|
||||||
queryAll,
|
queryAll,
|
||||||
} from "discourse/tests/helpers/qunit-helpers";
|
} from "discourse/tests/helpers/qunit-helpers";
|
||||||
import I18n from "I18n";
|
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));
|
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));
|
return results.filter((r) => !makeArray(context.tags).includes(r.id));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -246,9 +246,10 @@ class TagsController < ::ApplicationController
|
||||||
filter_params[:order_popularity] = true
|
filter_params[:order_popularity] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
tags_with_counts = DiscourseTagging.filter_allowed_tags(
|
tags_with_counts, filter_result_context = DiscourseTagging.filter_allowed_tags(
|
||||||
guardian,
|
guardian,
|
||||||
filter_params
|
**filter_params,
|
||||||
|
with_context: true
|
||||||
)
|
)
|
||||||
|
|
||||||
tags = self.class.tag_counts_json(tags_with_counts, show_pm_tags: guardian.can_tag_pms?)
|
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
|
||||||
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
|
render json: json_response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3836,6 +3836,9 @@ en:
|
||||||
choose_for_topic_required:
|
choose_for_topic_required:
|
||||||
one: "select at least %{count} tag..."
|
one: "select at least %{count} tag..."
|
||||||
other: "select at least %{count} tags..."
|
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"
|
info: "Info"
|
||||||
default_info: "This tag isn't restricted to any categories, and has no synonyms."
|
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>."
|
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
|
# - there are more available tags than the query limit
|
||||||
# - and no search term has been included
|
# - and no search term has been included
|
||||||
required_tag_ids = nil
|
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?)
|
if opts[:for_input] && category&.category_required_tag_groups.present? && (filter_for_non_staff || term.blank?)
|
||||||
category.category_required_tag_groups.each do |crtg|
|
category.category_required_tag_groups.each do |crtg|
|
||||||
group_tags = crtg.tag_group.tags.pluck(:id)
|
group_tags = crtg.tag_group.tags.pluck(:id)
|
||||||
next if (group_tags & selected_tag_ids).size >= crtg.min_count
|
next if (group_tags & selected_tag_ids).size >= crtg.min_count
|
||||||
if filter_for_non_staff || group_tags.size >= opts[:limit].to_i
|
if filter_for_non_staff || group_tags.size >= opts[:limit].to_i
|
||||||
|
required_category_tag_group = crtg
|
||||||
required_tag_ids = group_tags
|
required_tag_ids = group_tags
|
||||||
builder.where("id IN (?)", required_tag_ids)
|
builder.where("id IN (?)", required_tag_ids)
|
||||||
end
|
end
|
||||||
|
@ -441,6 +443,19 @@ module DiscourseTagging
|
||||||
end
|
end
|
||||||
|
|
||||||
result = builder.query(builder_params).uniq { |t| t.id }
|
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
|
end
|
||||||
|
|
||||||
def self.filter_visible(query, guardian = nil)
|
def self.filter_visible(query, guardian = nil)
|
||||||
|
|
|
@ -877,6 +877,28 @@ describe TagsController do
|
||||||
expect(response.status).to eq(400)
|
expect(response.status).to eq(400)
|
||||||
expect(response.parsed_body['errors'].first).to eq(I18n.t('invalid_params', message: 'limit'))
|
expect(response.parsed_body['errors'].first).to eq(I18n.t('invalid_params', message: 'limit'))
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue