FEATURE: filter personal messages by tags

This commit is contained in:
Arpit Jalan 2018-02-27 22:21:40 +05:30
parent 4132c37add
commit c29660c8f1
11 changed files with 109 additions and 2 deletions

View File

@ -12,6 +12,8 @@ export default Ember.Controller.extend({
currentPath: Em.computed.alias('application.currentPath'), currentPath: Em.computed.alias('application.currentPath'),
selected: Em.computed.alias('userTopicsList.selected'), selected: Em.computed.alias('userTopicsList.selected'),
bulkSelectEnabled: Em.computed.alias('userTopicsList.bulkSelectEnabled'), bulkSelectEnabled: Em.computed.alias('userTopicsList.bulkSelectEnabled'),
pmTags: Em.computed.alias('userTopicsList.model.topic_list.pm_tags'),
pmTaggingEnabled: Ember.computed.alias('site.can_tag_pms'),
showNewPM: function(){ showNewPM: function(){
return this.get('user.viewingSelf') && return this.get('user.viewingSelf') &&

View File

@ -65,7 +65,6 @@
</button> </button>
{{/if}} {{/if}}
{{#if bulkSelectEnabled}} {{#if bulkSelectEnabled}}
<button {{action "selectAll"}} class="btn btn-select-all"> <button {{action "selectAll"}} class="btn btn-select-all">
{{i18n "user.messages.select_all"}} {{i18n "user.messages.select_all"}}
@ -75,6 +74,10 @@
{{#if isGroup}} {{#if isGroup}}
{{group-notifications-button value=group.group_user.notification_level group=group user=model}} {{group-notifications-button value=group.group_user.notification_level group=group user=model}}
{{/if}} {{/if}}
{{#if pmTaggingEnabled}}
{{pm-tag-drop pmTags=pmTags}}
{{/if}}
</div> </div>
{{outlet}} {{outlet}}

View File

@ -0,0 +1,19 @@
import TagDropComponent from "select-kit/components/tag-drop";
import DiscourseURL from "discourse/lib/url";
import { default as computed } from "ember-addons/ember-computed-decorators";
export default TagDropComponent.extend({
@computed
allTagsUrl() {
return `/u/${this.currentUser.username}/messages/`;
},
content: Ember.computed.alias("pmTags"),
actions: {
onSelect(tagId) {
const url = `/u/${this.currentUser.username}/messages/tag/${tagId}`;
DiscourseURL.routeTo(url);
}
}
});

View File

@ -134,6 +134,7 @@ class ListController < ApplicationController
def self.generate_message_route(action) def self.generate_message_route(action)
define_method("#{action}") do define_method("#{action}") do
list_opts = build_topic_list_options list_opts = build_topic_list_options
list_opts[:show_pm_tags] = true if guardian.can_tag_pms?
target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) }, [:user_stat, :user_option]) target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) }, [:user_stat, :user_option])
guardian.ensure_can_see_private_messages!(target_user.id) guardian.ensure_can_see_private_messages!(target_user.id)
list = generate_list_for(action.to_s, target_user, list_opts) list = generate_list_for(action.to_s, target_user, list_opts)

View File

@ -59,6 +59,24 @@ class Tag < ActiveRecord::Base
tag_names_with_counts.map { |row| row['tag_name'] } tag_names_with_counts.map { |row| row['tag_name'] }
end end
def self.pm_tags(limit_arg: nil, guardian: nil)
return [] unless (guardian || Guardian.new).can_tag_pms?
limit = limit_arg || SiteSetting.max_tags_in_filter_list
tag_names = Tag.exec_sql <<~SQL
SELECT tags.name AS tag_name
FROM tags
INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
INNER JOIN topics ON topics.id = topic_tags.topic_id
AND topics.deleted_at IS NULL
AND topics.archetype = 'private_message'
GROUP BY tags.name
LIMIT #{limit}
SQL
tag_names.values.flatten
end
def self.include_tags? def self.include_tags?
SiteSetting.tagging_enabled && SiteSetting.show_filter_by_tag SiteSetting.tagging_enabled && SiteSetting.show_filter_by_tag
end end

View File

@ -35,6 +35,7 @@ class TopicList
:for_period, :for_period,
:per_page, :per_page,
:top_tags, :top_tags,
:pm_tags,
:current_user, :current_user,
:tags :tags
@ -59,6 +60,15 @@ class TopicList
Tag.top_tags(opts) Tag.top_tags(opts)
end end
def pm_tags
guardian = Guardian.new(@current_user)
if @opts[:show_pm_tags] && guardian.can_tag_pms?
Tag.pm_tags(guardian: guardian)
else
[]
end
end
def preload_key def preload_key
if @category if @category
"topic_list_#{@category.url.sub(/^\//, '')}/l/#{@filter}" "topic_list_#{@category.url.sub(/^\//, '')}/l/#{@filter}"

View File

@ -8,6 +8,7 @@ class TopicListSerializer < ApplicationSerializer
:for_period, :for_period,
:per_page, :per_page,
:top_tags, :top_tags,
:pm_tags,
:tags :tags
has_many :topics, serializer: TopicListItemSerializer, embed: :objects has_many :topics, serializer: TopicListItemSerializer, embed: :objects
@ -29,6 +30,10 @@ class TopicListSerializer < ApplicationSerializer
Tag.include_tags? Tag.include_tags?
end end
def include_pm_tags?
scope.can_tag_pms?
end
def include_tags? def include_tags?
SiteSetting.tagging_enabled && object.tags.present? SiteSetting.tagging_enabled && object.tags.present?
end end

View File

@ -32,7 +32,8 @@ class TopicQuery
match_all_tags match_all_tags
no_subcategories no_subcategories
slow_platform slow_platform
no_tags) no_tags
show_pm_tags)
end end
def self.valid_options def self.valid_options

View File

@ -96,6 +96,28 @@ describe Tag do
end end
end end
describe '#pm_tags' do
before do
@private_tags = []
personal_message = Fabricate(:private_message_topic)
2.times { |i| @private_tags << Fabricate(:tag, topics: [personal_message]) }
end
it "returns nothing if user is not a staff" do
expect(described_class.pm_tags.sort).to be_empty
end
it "returns nothing if allow_staff_to_tag_pms setting is disabled" do
SiteSetting.allow_staff_to_tag_pms = false
expect(described_class.pm_tags(guardian: Guardian.new(Fabricate(:admin))).sort).to be_empty
end
it "returns all pm tags if user is a staff and pm tagging is enabled" do
SiteSetting.allow_staff_to_tag_pms = true
expect(described_class.pm_tags(guardian: Guardian.new(Fabricate(:admin)))).to match_array(@private_tags.map(&:name))
end
end
context "topic counts" do context "topic counts" do
it "should exclude private message topics" do it "should exclude private message topics" do
topic topic

View File

@ -78,4 +78,28 @@ describe TopicList do
end end
end end
end end
describe '#pm_tags' do
let(:admin) { Fabricate(:admin) }
let(:personal_message) { Fabricate(:private_message_topic) }
before do
SiteSetting.tagging_enabled = true
SiteSetting.allow_staff_to_tag_pms = true
@private_tags = []
2.times { |i| @private_tags << Fabricate(:tag, topics: [personal_message]) }
end
context 'when viewed as normal user' do
it 'returns no tags' do
expect(TopicList.new('liked', personal_message.user, [personal_message], show_pm_tags: true).pm_tags).to be_empty
end
end
context 'when viewed as admin' do
it 'returns pm tags' do
expect(TopicList.new('liked', admin, [personal_message], show_pm_tags: true).pm_tags).to match_array(@private_tags.map(&:name))
end
end
end
end end

View File

@ -105,6 +105,8 @@ RSpec.describe ListController do
sign_in(user) sign_in(user)
get "/topics/private-messages-tag/#{user.username}/#{tag.name}.json" get "/topics/private-messages-tag/#{user.username}/#{tag.name}.json"
expect(response).to be_success expect(response).to be_success
data = JSON.parse(response.body)
expect(data["topic_list"]["pm_tags"].length).to eq(1)
end end
end end
end end