FEATURE: add filter to show topics that have not been tagged
This commit is contained in:
parent
8e87a727ef
commit
7c092b0fe0
|
@ -45,6 +45,20 @@ export default Ember.Component.extend({
|
|||
return I18n.t("tagging.selector_all_tags");
|
||||
}.property('tag'),
|
||||
|
||||
@computed('firstCategory', 'secondCategory')
|
||||
noTagsUrl() {
|
||||
var url = '/tags';
|
||||
if (this.get('currentCategory')) {
|
||||
url += this.get('currentCategory.url');
|
||||
}
|
||||
return url + '/none';
|
||||
},
|
||||
|
||||
@computed('tag')
|
||||
noTagsLabel() {
|
||||
return I18n.t("tagging.selector_no_tags");
|
||||
},
|
||||
|
||||
dropdownButtonClass: function() {
|
||||
var result = 'badge-category category-dropdown-button';
|
||||
if (Em.isNone(this.get('tag'))) {
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Discourse.Route.extend({
|
|||
},
|
||||
|
||||
model(params) {
|
||||
var tag = this.store.createRecord("tag", { id: Handlebars.Utils.escapeExpression(params.tag_id) }),
|
||||
var tag = (params.tag_id === 'none' ? null : this.store.createRecord("tag", { id: Handlebars.Utils.escapeExpression(params.tag_id) })),
|
||||
f = '';
|
||||
|
||||
if (params.category) {
|
||||
|
@ -25,8 +25,8 @@ export default Discourse.Route.extend({
|
|||
if (params.category) { this.set('categorySlug', params.category); }
|
||||
if (params.parent_category) { this.set('parentCategorySlug', params.parent_category); }
|
||||
|
||||
if (this.get("currentUser")) {
|
||||
// If logged in, we should get the tag"s user settings
|
||||
if (tag && this.get("currentUser")) {
|
||||
// If logged in, we should get the tag's user settings
|
||||
return this.store.find("tagNotification", tag.get("id")).then(tn => {
|
||||
this.set("tagNotification", tn);
|
||||
return tag;
|
||||
|
@ -45,18 +45,19 @@ export default Discourse.Route.extend({
|
|||
const categorySlug = this.get('categorySlug');
|
||||
const parentCategorySlug = this.get('parentCategorySlug');
|
||||
const filter = this.get('navMode');
|
||||
const tag_id = (tag ? tag.id : 'none');
|
||||
|
||||
if (categorySlug) {
|
||||
var category = Discourse.Category.findBySlug(categorySlug, parentCategorySlug);
|
||||
if (parentCategorySlug) {
|
||||
params.filter = `tags/c/${parentCategorySlug}/${categorySlug}/${tag.id}/l/${filter}`;
|
||||
params.filter = `tags/c/${parentCategorySlug}/${categorySlug}/${tag_id}/l/${filter}`;
|
||||
} else {
|
||||
params.filter = `tags/c/${categorySlug}/${tag.id}/l/${filter}`;
|
||||
params.filter = `tags/c/${categorySlug}/${tag_id}/l/${filter}`;
|
||||
}
|
||||
|
||||
this.set('category', category);
|
||||
} else {
|
||||
params.filter = `tags/${tag.id}/l/${filter}`;
|
||||
params.filter = `tags/${tag_id}/l/${filter}`;
|
||||
this.set('category', null);
|
||||
}
|
||||
|
||||
|
@ -74,10 +75,18 @@ export default Discourse.Route.extend({
|
|||
const filterText = I18n.t('filters.' + this.get('navMode').replace('/', '.') + '.title'),
|
||||
controller = this.controllerFor('tags.show');
|
||||
|
||||
if (this.get('category')) {
|
||||
return I18n.t('tagging.filters.with_category', { filter: filterText, tag: controller.get('model.id'), category: this.get('category.name')});
|
||||
if (controller.get('model.id')) {
|
||||
if (this.get('category')) {
|
||||
return I18n.t('tagging.filters.with_category', { filter: filterText, tag: controller.get('model.id'), category: this.get('category.name')});
|
||||
} else {
|
||||
return I18n.t('tagging.filters.without_category', { filter: filterText, tag: controller.get('model.id')});
|
||||
}
|
||||
} else {
|
||||
return I18n.t('tagging.filters.without_category', { filter: filterText, tag: controller.get('model.id')});
|
||||
if (this.get('category')) {
|
||||
return I18n.t('tagging.filters.untagged_with_category', { filter: filterText, category: this.get('category.name')});
|
||||
} else {
|
||||
return I18n.t('tagging.filters.untagged_without_category', { filter: filterText});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{{#if tagId}}
|
||||
<a href {{action "expand"}} class="badge-category {{tagClass}}">{{tagId}}</a>
|
||||
{{else}}
|
||||
<!-- TODO: how to detect "no tags" is currently selected -->
|
||||
<a href {{action "expand"}} class="badge-category {{tagClass}} home">{{allTagsLabel}}</a>
|
||||
{{/if}}
|
||||
|
||||
|
@ -9,6 +10,7 @@
|
|||
<a href {{action "expand"}} class={{dropdownButtonClass}}><i class={{iconClass}}></i></a>
|
||||
<section class="{{unless expanded 'hidden'}} category-dropdown-menu chooser">
|
||||
<div class='cat'><a href={{allTagsUrl}} data-drop-close="true" class='badge-category home'>{{allTagsLabel}}</a></div>
|
||||
<div class='cat'><a href={{noTagsUrl}} data-drop-close="true" class='badge-category home'>{{noTagsLabel}}</a></div>
|
||||
{{#if renderTags}}
|
||||
{{#each tags as |t|}}
|
||||
<div class='cat'>
|
||||
|
|
|
@ -57,7 +57,7 @@ class TagsController < ::ApplicationController
|
|||
@list.more_topics_url = list_by_tag_path(tag_id: @tag_id, page: page + 1)
|
||||
@rss = "tag"
|
||||
|
||||
if @list.topics.size == 0 && !Tag.where(name: @tag_id).exists?
|
||||
if @list.topics.size == 0 && params[:tag_id] != 'none' && !Tag.where(name: @tag_id).exists?
|
||||
raise Discourse::NotFound
|
||||
else
|
||||
respond_with_list(@list)
|
||||
|
@ -203,7 +203,6 @@ class TagsController < ::ApplicationController
|
|||
topic_ids: param_to_integer_list(:topic_ids),
|
||||
exclude_category_ids: params[:exclude_category_ids],
|
||||
category: params[:category],
|
||||
tags: [params[:tag_id]],
|
||||
order: params[:order],
|
||||
ascending: params[:ascending],
|
||||
min_posts: params[:min_posts],
|
||||
|
@ -217,6 +216,12 @@ class TagsController < ::ApplicationController
|
|||
options[:no_subcategories] = true if params[:no_subcategories] == 'true'
|
||||
options[:slow_platform] = true if slow_platform?
|
||||
|
||||
if params[:tag_id] == 'none'
|
||||
options[:no_tags] = true
|
||||
else
|
||||
options[:tags] = [params[:tag_id]]
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
|
|
|
@ -2123,6 +2123,7 @@ en:
|
|||
tagging:
|
||||
all_tags: "All Tags"
|
||||
selector_all_tags: "all tags"
|
||||
selector_no_tags: "no tags"
|
||||
changed: "tags changed:"
|
||||
tags: "Tags"
|
||||
choose_for_topic: "choose optional tags for this topic"
|
||||
|
@ -2139,6 +2140,8 @@ en:
|
|||
filters:
|
||||
without_category: "%{filter} %{tag} topics"
|
||||
with_category: "%{filter} %{tag} topics in %{category}"
|
||||
untagged_without_category: "%{filter} untagged topics"
|
||||
untagged_with_category: "%{filter} untagged topics in %{category}"
|
||||
|
||||
notifications:
|
||||
watching:
|
||||
|
|
|
@ -20,6 +20,7 @@ class TopicQuery
|
|||
visible
|
||||
category
|
||||
tags
|
||||
no_tags
|
||||
order
|
||||
ascending
|
||||
no_subcategories
|
||||
|
@ -465,6 +466,9 @@ class TopicQuery
|
|||
else
|
||||
result = result.where("tags.name in (?)", @options[:tags])
|
||||
end
|
||||
elsif @options[:no_tags]
|
||||
# the following will do: ("topics"."id" NOT IN (SELECT DISTINCT "topic_tags"."topic_id" FROM "topic_tags"))
|
||||
result = result.where.not(:id => TopicTag.select(:topic_id).uniq)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -122,25 +122,32 @@ describe TopicQuery do
|
|||
SiteSetting.tagging_enabled = true
|
||||
end
|
||||
|
||||
it "returns topics with the tag when filtered to it" do
|
||||
tagged_topic1 = Fabricate(:topic, {tags: [tag]})
|
||||
tagged_topic2 = Fabricate(:topic, {tags: [other_tag]})
|
||||
tagged_topic3 = Fabricate(:topic, {tags: [tag, other_tag]})
|
||||
no_tags_topic = Fabricate(:topic)
|
||||
context "no category filter" do
|
||||
# create some topics before each test:
|
||||
let!(:tagged_topic1) { Fabricate(:topic, {tags: [tag]}) }
|
||||
let!(:tagged_topic2) { Fabricate(:topic, {tags: [other_tag]}) }
|
||||
let!(:tagged_topic3) { Fabricate(:topic, {tags: [tag, other_tag]}) }
|
||||
let!(:no_tags_topic) { Fabricate(:topic) }
|
||||
|
||||
expect(TopicQuery.new(moderator, tags: [tag.name]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic3.id].sort)
|
||||
expect(TopicQuery.new(moderator, tags: [tag.id]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic3.id].sort)
|
||||
it "returns topics with the tag when filtered to it" do
|
||||
expect(TopicQuery.new(moderator, tags: [tag.name]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic3.id].sort)
|
||||
expect(TopicQuery.new(moderator, tags: [tag.id]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic3.id].sort)
|
||||
|
||||
two_tag_topic = TopicQuery.new(moderator, tags: [tag.name]).list_latest.topics.find { |t| t.id == tagged_topic3.id }
|
||||
expect(two_tag_topic.tags.size).to eq(2)
|
||||
two_tag_topic = TopicQuery.new(moderator, tags: [tag.name]).list_latest.topics.find { |t| t.id == tagged_topic3.id }
|
||||
expect(two_tag_topic.tags.size).to eq(2)
|
||||
|
||||
# topics with ANY of the given tags:
|
||||
expect(TopicQuery.new(moderator, tags: [tag.name, other_tag.name]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic2.id, tagged_topic3.id].sort)
|
||||
expect(TopicQuery.new(moderator, tags: [tag.id, other_tag.id]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic2.id, tagged_topic3.id].sort)
|
||||
# topics with ANY of the given tags:
|
||||
expect(TopicQuery.new(moderator, tags: [tag.name, other_tag.name]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic2.id, tagged_topic3.id].sort)
|
||||
expect(TopicQuery.new(moderator, tags: [tag.id, other_tag.id]).list_latest.topics.map(&:id).sort).to eq([tagged_topic1.id, tagged_topic2.id, tagged_topic3.id].sort)
|
||||
|
||||
# TODO: topics with ALL of the given tags:
|
||||
# expect(TopicQuery.new(moderator, tags: [tag.name, other_tag.name]).list_latest.topics.map(&:id)).to eq([tagged_topic3.id].sort)
|
||||
# expect(TopicQuery.new(moderator, tags: [tag.id, other_tag.id]).list_latest.topics.map(&:id)).to eq([tagged_topic3.id].sort)
|
||||
# TODO: topics with ALL of the given tags:
|
||||
# expect(TopicQuery.new(moderator, tags: [tag.name, other_tag.name]).list_latest.topics.map(&:id)).to eq([tagged_topic3.id].sort)
|
||||
# expect(TopicQuery.new(moderator, tags: [tag.id, other_tag.id]).list_latest.topics.map(&:id)).to eq([tagged_topic3.id].sort)
|
||||
end
|
||||
|
||||
it "can return topics with no tags" do
|
||||
expect(TopicQuery.new(moderator, no_tags: true).list_latest.topics.map(&:id)).to eq([no_tags_topic.id])
|
||||
end
|
||||
end
|
||||
|
||||
context "and categories too" do
|
||||
|
|
Loading…
Reference in New Issue