FEATURE: allow users to archive messages

Messages are now in 3 buckets

- Inbox for all new messages
- Sent for all sent messages
- Archive for all messages you are done with

You can select messages from your Inbox or Sent and move them to your Archive,
you can move messages out of your Archive similarly

Similar concept applied to group messages, except that archiving and unarchiving
will apply to all group members
This commit is contained in:
Sam 2015-12-23 11:09:17 +11:00
parent e03861da7e
commit 03ea0bfe22
30 changed files with 290 additions and 57 deletions

View File

@ -1,4 +1,5 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
loadingMore: Ember.computed.alias('topicList.loadingMore'),
loading: Ember.computed.not('loaded'), loading: Ember.computed.not('loaded'),
loaded: function() { loaded: function() {

View File

@ -1,25 +1,62 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from 'ember-addons/ember-computed-decorators';
import Topic from 'discourse/models/topic';
export default Ember.Controller.extend({ export default Ember.Controller.extend({
needs: ["user-topics-list"],
pmView: false, pmView: false,
privateMessagesActive: Em.computed.equal('pmView', 'index'),
privateMessagesMineActive: Em.computed.equal('pmView', 'mine'),
privateMessagesUnreadActive: Em.computed.equal('pmView', 'unread'),
isGroup: Em.computed.equal('pmView', 'groups'), isGroup: Em.computed.equal('pmView', 'groups'),
selected: Em.computed.alias('controllers.user-topics-list.selected'),
bulkSelectEnabled: Em.computed.alias('controllers.user-topics-list.bulkSelectEnabled'),
@computed('model.groups', 'groupFilter', 'pmView') @computed('selected.@each', 'bulkSelectEnabled')
groupPMStats(groups, filter, pmView) { hasSelection(selected, bulkSelectEnabled){
if (groups) { return bulkSelectEnabled && selected && selected.length > 0;
return groups.filter(group => group.has_messages) },
.map(g => {
return { @computed('hasSelection', 'pmView', 'archive')
name: g.name, canMoveToInbox(hasSelection, pmView, archive){
active: (g.name === filter && pmView === "groups") return hasSelection && (pmView === "archive" || archive);
}; },
});
@computed('hasSelection', 'pmView', 'archive')
canArchive(hasSelection, pmView, archive){
return hasSelection && pmView !== "archive" && !archive;
},
bulkOperation(operation) {
const selected = this.get('selected');
var params = {type: operation};
if (this.get('isGroup')) {
params.group = this.get('groupFilter');
}
Topic.bulkOperation(selected,params).then(() => {
const model = this.get('controllers.user-topics-list.model');
const topics = model.get('topics');
topics.removeObjects(selected);
selected.clear();
model.loadMore();
}, () => {
bootbox.alert(I18n.t("user.messages.failed_to_move"));
});
},
actions: {
archive() {
this.bulkOperation("archive_messages");
},
toInbox() {
this.bulkOperation("move_messages_to_inbox");
},
toggleBulkSelect(){
this.toggleProperty("bulkSelectEnabled");
},
selectAll() {
$('input.bulk-select:not(checked)').click();
} }
} }
}); });

View File

@ -17,6 +17,6 @@ export default Ember.Controller.extend({
showNewPM: function(){ showNewPM: function(){
return this.get('controllers.user.viewingSelf') && return this.get('controllers.user.viewingSelf') &&
Discourse.User.currentProp('can_send_private_messages'); Discourse.User.currentProp('can_send_private_messages');
}.property('controllers.user.viewingSelf'), }.property('controllers.user.viewingSelf')
}); });

View File

@ -0,0 +1,3 @@
Ember.Handlebars.registerBoundHelper("capitalize", function(str) {
return str[0].toUpperCase() + str.slice(1);
});

View File

@ -76,9 +76,10 @@ export default function() {
this.route('deletedPosts', { path: '/deleted-posts' }); this.route('deletedPosts', { path: '/deleted-posts' });
this.resource('userPrivateMessages', { path: '/messages' }, function() { this.resource('userPrivateMessages', { path: '/messages' }, function() {
this.route('mine'); this.route('sent');
this.route('unread'); this.route('archive');
this.route('group', { path: 'group/:name'}); this.route('group', { path: 'group/:name'});
this.route('groupArchive', { path: 'group/:name/archive'});
}); });
this.resource('preferences', function() { this.resource('preferences', function() {

View File

@ -21,10 +21,13 @@ export default (viewName, path) => {
this.controllerFor("user-topics-list").setProperties({ this.controllerFor("user-topics-list").setProperties({
hideCategory: true, hideCategory: true,
showParticipants: true showParticipants: true,
canBulkSelect: true,
selected: []
}); });
this.controllerFor("userPrivateMessages").set("pmView", viewName); this.controllerFor("user-private-messages").set("archive", false);
this.controllerFor("user-private-messages").set("pmView", viewName);
this.searchService.set('contextType', 'private_messages'); this.searchService.set('contextType', 'private_messages');
}, },

View File

@ -1,3 +1,3 @@
import createPMRoute from "discourse/routes/build-private-messages-route"; import createPMRoute from "discourse/routes/build-private-messages-route";
export default createPMRoute('unread', 'private-messages-unread'); export default createPMRoute('archive', 'private-messages-archive');

View File

@ -0,0 +1,18 @@
import createPMRoute from "discourse/routes/build-private-messages-route";
export default createPMRoute('groups', 'private-messages-groups').extend({
model(params) {
const username = this.modelFor("user").get("username_lower");
return this.store.findFiltered("topicList", {
filter: `topics/private-messages-group/${username}/${params.name}/archive`
});
},
setupController(controller, model) {
this._super.apply(this, arguments);
const split = model.get("filter").split('/');
const group = split[split.length-2];
this.controllerFor("user-private-messages").set("groupFilter", group);
this.controllerFor("user-private-messages").set("archive", true);
}
});

View File

@ -1,4 +1,3 @@
import Group from 'discourse/models/group';
import createPMRoute from "discourse/routes/build-private-messages-route"; import createPMRoute from "discourse/routes/build-private-messages-route";
export default createPMRoute('groups', 'private-messages-groups').extend({ export default createPMRoute('groups', 'private-messages-groups').extend({
@ -9,17 +8,10 @@ export default createPMRoute('groups', 'private-messages-groups').extend({
}); });
}, },
afterModel(model) {
const groupName = _.last(model.get("filter").split('/'));
Group.findAll().then(groups => {
const group = _.first(groups.filterBy("name", groupName));
this.controllerFor("user-private-messages").set("group", group);
});
},
setupController(controller, model) { setupController(controller, model) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
const group = _.last(model.get("filter").split('/')); const group = _.last(model.get("filter").split('/'));
this.controllerFor("userPrivateMessages").set("groupFilter", group); this.controllerFor("user-private-messages").set("groupFilter", group);
this.controllerFor("user-private-messages").set("archive", false);
} }
}); });

View File

@ -1,3 +1,3 @@
import createPMRoute from "discourse/routes/build-private-messages-route"; import createPMRoute from "discourse/routes/build-private-messages-route";
export default createPMRoute('mine', 'private-messages-sent'); export default createPMRoute('sent', 'private-messages-sent');

View File

@ -5,10 +5,15 @@
hideCategory=hideCategory hideCategory=hideCategory
topics=topics topics=topics
expandExcerpts=expandExcerpts expandExcerpts=expandExcerpts
bulkSelectEnabled=bulkSelectEnabled
canBulkSelect=canBulkSelect
selected=selected
}} }}
{{else}} {{else}}
{{#unless loadingMore}}
<div class='alert alert-info'> <div class='alert alert-info'>
{{i18n 'choose_topic.none_found'}} {{i18n 'choose_topic.none_found'}}
</div> </div>
{{/unless}}
{{/if}} {{/if}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}

View File

@ -2,4 +2,7 @@
{{basic-topic-list topicList=model {{basic-topic-list topicList=model
hideCategory=hideCategory hideCategory=hideCategory
showParticipants=showParticipants showParticipants=showParticipants
canBulkSelect=canBulkSelect
bulkSelectEnabled=bulkSelectEnabled
selected=selected
postsAction="showTopicEntrance"}} postsAction="showTopicEntrance"}}

View File

@ -1,30 +1,34 @@
<section class='user-navigation'> <section class='user-navigation'>
<ul class='action-list nav-stacked'> <ul class='action-list nav-stacked'>
<li {{bind-attr class=":noGlyph privateMessagesActive:active"}}> <li class="noGlyph">
{{#link-to 'userPrivateMessages.index' model}} {{#link-to 'userPrivateMessages.index' model}}
{{i18n 'user.messages.all'}} {{i18n 'user.messages.inbox'}}
{{#if model.hasPMs}}<span class='count'>({{model.private_messages_stats.all}})</span>{{/if}}
{{/link-to}} {{/link-to}}
</li> </li>
<li {{bind-attr class=":noGlyph privateMessagesMineActive:active"}}> <li class="noGlyph">
{{#link-to 'userPrivateMessages.mine' model}} {{#link-to 'userPrivateMessages.sent' model}}
{{i18n 'user.messages.mine'}} {{i18n 'user.messages.sent'}}
{{#if model.hasStartedPMs}}<span class='count'>({{model.private_messages_stats.mine}})</span>{{/if}}
{{/link-to}} {{/link-to}}
</li> </li>
<li {{bind-attr class=":noGlyph privateMessagesUnreadActive:active"}}> <li class="noGlyph">
{{#link-to 'userPrivateMessages.unread' model}} {{#link-to 'userPrivateMessages.archive' model}}
{{i18n 'user.messages.unread'}} {{i18n 'user.messages.archive'}}
{{#if model.hasUnreadPMs}}<span class='badge-notification unread-private-messages'>{{model.private_messages_stats.unread}}</span>{{/if}}
{{/link-to}} {{/link-to}}
</li> </li>
{{#each groupPMStats as |group|}} {{#each model.groups as |group|}}
<li class="{{if group.active "active"}}"> {{#if group.has_messages}}
<li>
{{#link-to 'userPrivateMessages.group' group.name}} {{#link-to 'userPrivateMessages.group' group.name}}
<i class='glyph fa fa-group'></i> <i class='glyph fa fa-group'></i>
{{group.name}} {{capitalize group.name}}
{{/link-to}} {{/link-to}}
</li> </li>
<li>
{{#link-to 'userPrivateMessages.groupArchive' group.name}}
{{i18n 'user.messages.archive'}}
{{/link-to}}
</li>
{{/if}}
{{/each}} {{/each}}
</ul> </ul>
@ -33,11 +37,34 @@
<section class='user-right messages'> <section class='user-right messages'>
{{#if isGroup}} <div class="clearfix list-actions">
<div class="clearfix"> <button {{action "toggleBulkSelect"}} class="btn bulk-select" title="{{i18n "user.messages.bulk_select"}}">
{{group-notifications-button group=group}} <i class="fa fa-list"></i>
</button>
{{#if canArchive}}
<button {{action "archive"}} class="btn btn-archive">
{{i18n "user.messages.archive"}}
</button>
{{/if}}
{{#if canMoveToInbox}}
<button {{action "toInbox"}} class="btn btn-to-inbox">
{{i18n "user.messages.move_to_inbox"}}
</button>
{{/if}}
{{#if bulkSelectEnabled}}
<button {{action "selectAll"}} class="btn btn-select-all">
{{i18n "user.messages.select_all"}}
</button>
{{/if}}
{{#if isGroup}}
{{group-notifications-button group=group}}
{{/if}}
</div> </div>
{{/if}}
{{outlet}} {{outlet}}
</section> </section>

View File

@ -92,6 +92,7 @@
//= require ./discourse/components/conditional-loading-spinner //= require ./discourse/components/conditional-loading-spinner
//= require ./discourse/helpers/user-avatar //= require ./discourse/helpers/user-avatar
//= require ./discourse/helpers/cold-age-class //= require ./discourse/helpers/cold-age-class
//= require ./discourse/helpers/capitalize
//= require ./discourse/helpers/loading-spinner //= require ./discourse/helpers/loading-spinner
//= require ./discourse/helpers/category-link //= require ./discourse/helpers/category-link
//= require ./discourse/lib/export-result //= require ./discourse/lib/export-result

View File

@ -162,3 +162,9 @@
} }
} }
.user-right .list-actions {
margin-bottom: 10px;
.btn {
margin-right: 10px;
}
}

View File

@ -102,7 +102,7 @@ class ListController < ApplicationController
end end
end end
[:topics_by, :private_messages, :private_messages_sent, :private_messages_unread, :private_messages_group].each do |action| [:topics_by, :private_messages, :private_messages_sent, :private_messages_unread, :private_messages_archive, :private_messages_group, :private_messages_group_archive].each do |action|
define_method("#{action}") do define_method("#{action}") do
list_opts = build_topic_list_options list_opts = build_topic_list_options
target_user = fetch_user_from_params(include_inactive: current_user.try(:staff?)) target_user = fetch_user_from_params(include_inactive: current_user.try(:staff?))

View File

@ -451,7 +451,7 @@ class TopicsController < ApplicationController
operation = params.require(:operation).symbolize_keys operation = params.require(:operation).symbolize_keys
raise ActionController::ParameterMissing.new(:operation_type) if operation[:type].blank? raise ActionController::ParameterMissing.new(:operation_type) if operation[:type].blank?
operator = TopicsBulkAction.new(current_user, topic_ids, operation) operator = TopicsBulkAction.new(current_user, topic_ids, operation, group: operation[:group])
changed_topic_ids = operator.perform! changed_topic_ids = operator.perform!
render_json_dump topic_ids: changed_topic_ids render_json_dump topic_ids: changed_topic_ids
end end

View File

@ -5,6 +5,8 @@ class Group < ActiveRecord::Base
has_many :group_users, dependent: :destroy has_many :group_users, dependent: :destroy
has_many :group_mentions, dependent: :destroy has_many :group_mentions, dependent: :destroy
has_many :group_archived_messages, dependent: :destroy
has_many :categories, through: :category_groups has_many :categories, through: :category_groups
has_many :users, through: :group_users has_many :users, through: :group_users

View File

@ -0,0 +1,4 @@
class GroupArchivedMessage < ActiveRecord::Base
belongs_to :user
belongs_to :topic
end

View File

@ -83,6 +83,9 @@ class Topic < ActiveRecord::Base
has_many :topic_allowed_users has_many :topic_allowed_users
has_many :topic_allowed_groups has_many :topic_allowed_groups
has_many :group_archived_messages, dependent: :destroy
has_many :user_archived_messages, dependent: :destroy
has_many :allowed_group_users, through: :allowed_groups, source: :users has_many :allowed_group_users, through: :allowed_groups, source: :users
has_many :allowed_groups, through: :topic_allowed_groups, source: :group has_many :allowed_groups, through: :topic_allowed_groups, source: :group
has_many :allowed_users, through: :topic_allowed_users, source: :user has_many :allowed_users, through: :topic_allowed_users, source: :user

View File

@ -35,6 +35,8 @@ class User < ActiveRecord::Base
has_many :topic_links, dependent: :destroy has_many :topic_links, dependent: :destroy
has_many :uploads has_many :uploads
has_many :warnings has_many :warnings
has_many :user_archived_messages, dependent: :destroy
has_one :user_avatar, dependent: :destroy has_one :user_avatar, dependent: :destroy
has_one :facebook_user_info, dependent: :destroy has_one :facebook_user_info, dependent: :destroy

View File

@ -0,0 +1,4 @@
class UserArchivedMessage < ActiveRecord::Base
belongs_to :user
belongs_to :topic
end

View File

@ -504,9 +504,14 @@ en:
messages: messages:
all: "All" all: "All"
mine: "Mine" inbox: "Inbox"
unread: "Unread" sent: "Sent"
archive: "Archive"
groups: "My Groups" groups: "My Groups"
bulk_select: "Select messages"
move_to_inbox: "Move to Inbox"
failed_to_move: "Failed to move selected messages (perhaps your network is down)"
select_all: "Select All"
change_password: change_password:
success: "(email sent)" success: "(email sent)"

View File

@ -279,6 +279,9 @@ Discourse::Application.routes.draw do
get "users/:username/messages" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT} get "users/:username/messages" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
get "users/:username/messages/:filter" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT} get "users/:username/messages/:filter" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
get "users/:username/messages/group/:group_name" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT, group_name: USERNAME_ROUTE_FORMAT} get "users/:username/messages/group/:group_name" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT, group_name: USERNAME_ROUTE_FORMAT}
get "users/:username/messages/group/:group_name/archive" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT, group_name: USERNAME_ROUTE_FORMAT}
get "users/:username.json" => "users#show", constraints: {username: USERNAME_ROUTE_FORMAT}, defaults: {format: :json} get "users/:username.json" => "users#show", constraints: {username: USERNAME_ROUTE_FORMAT}, defaults: {format: :json}
get "users/:username" => "users#show", as: 'user', constraints: {username: USERNAME_ROUTE_FORMAT} get "users/:username" => "users#show", as: 'user', constraints: {username: USERNAME_ROUTE_FORMAT}
put "users/:username" => "users#update", constraints: {username: USERNAME_ROUTE_FORMAT} put "users/:username" => "users#update", constraints: {username: USERNAME_ROUTE_FORMAT}
@ -468,12 +471,18 @@ Discourse::Application.routes.draw do
get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT} get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT}
get "topics/private-messages/:username" => "list#private_messages", as: "topics_private_messages", constraints: {username: USERNAME_ROUTE_FORMAT} get "topics/private-messages/:username" => "list#private_messages", as: "topics_private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
get "topics/private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", constraints: {username: USERNAME_ROUTE_FORMAT} get "topics/private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", constraints: {username: USERNAME_ROUTE_FORMAT}
get "topics/private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive", constraints: {username: USERNAME_ROUTE_FORMAT}
get "topics/private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", constraints: {username: USERNAME_ROUTE_FORMAT} get "topics/private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", constraints: {username: USERNAME_ROUTE_FORMAT}
get "topics/private-messages-group/:username/:group_name.json" => "list#private_messages_group", as: "topics_private_messages_group", constraints: { get "topics/private-messages-group/:username/:group_name.json" => "list#private_messages_group", as: "topics_private_messages_group", constraints: {
username: USERNAME_ROUTE_FORMAT, username: USERNAME_ROUTE_FORMAT,
group_name: USERNAME_ROUTE_FORMAT group_name: USERNAME_ROUTE_FORMAT
} }
get "topics/private-messages-group/:username/:group_name/archive.json" => "list#private_messages_group_archive", as: "topics_private_messages_group_archive", constraints: {
username: USERNAME_ROUTE_FORMAT,
group_name: USERNAME_ROUTE_FORMAT
}
get 'embed/comments' => 'embed#comments' get 'embed/comments' => 'embed#comments'
get 'embed/count' => 'embed#count' get 'embed/count' => 'embed#count'
get 'embed/info' => 'embed#info' get 'embed/info' => 'embed#info'

View File

@ -0,0 +1,19 @@
class AddUserArchivedMessagesGroupArchivedMessages < ActiveRecord::Migration
def change
create_table :user_archived_messages do |t|
t.integer :user_id, null: false
t.integer :topic_id, null: false
t.timestamps
end
add_index :user_archived_messages, [:user_id, :topic_id], unique: true
create_table :group_archived_messages do |t|
t.integer :group_id, null: false
t.integer :topic_id, null: false
t.timestamps
end
add_index :group_archived_messages, [:group_id, :topic_id], unique: true
end
end

View File

@ -134,6 +134,7 @@ class PostCreator
create_embedded_topic create_embedded_topic
ensure_in_allowed_users if guardian.is_staff? ensure_in_allowed_users if guardian.is_staff?
unarchive_message
@post.advance_draft_sequence @post.advance_draft_sequence
@post.save_reply_relationships @post.save_reply_relationships
end end
@ -268,6 +269,13 @@ class PostCreator
end end
end end
def unarchive_message
return unless @topic.private_message? && @topic.id
UserArchivedMessage.where(topic_id: @topic.id).destroy_all
GroupArchivedMessage.where(topic_id: @topic.id).destroy_all
end
private private
def create_topic def create_topic

View File

@ -117,14 +117,35 @@ class TopicQuery
end end
end end
def not_archived(list, user)
list.joins("LEFT JOIN user_archived_messages um
ON um.user_id = #{user.id.to_i} AND um.topic_id = topics.id")
.where('um.user_id IS NULL')
end
def list_private_messages(user) def list_private_messages(user)
list = private_messages_for(user, :user) list = private_messages_for(user, :user)
list = not_archived(list, user)
.where('NOT (topics.participant_count = 1 AND topics.user_id = ?)', user.id)
create_list(:private_messages, {}, list)
end
def list_private_messages_archive(user)
list = private_messages_for(user, :user)
list = list.joins(:user_archived_messages).where('user_archived_messages.user_id = ?', user.id)
create_list(:private_messages, {}, list) create_list(:private_messages, {}, list)
end end
def list_private_messages_sent(user) def list_private_messages_sent(user)
list = private_messages_for(user, :user) list = private_messages_for(user, :user)
list = list.where(user_id: user.id) list = list.where('EXISTS (
SELECT 1 FROM posts
WHERE posts.topic_id = topics.id AND
posts.user_id = ?
)', user.id)
list = not_archived(list, user)
create_list(:private_messages, {}, list) create_list(:private_messages, {}, list)
end end
@ -136,6 +157,18 @@ class TopicQuery
def list_private_messages_group(user) def list_private_messages_group(user)
list = private_messages_for(user, :group) list = private_messages_for(user, :group)
group_id = Group.where('name ilike ?', @options[:group_name]).pluck(:id).first
list = list.joins("LEFT JOIN group_archived_messages gm ON gm.topic_id = topics.id AND
gm.group_id = #{group_id.to_i}")
list = list.where("gm.id IS NULL")
create_list(:private_messages, {}, list)
end
def list_private_messages_group_archive(user)
list = private_messages_for(user, :group)
group_id = Group.where('name ilike ?', @options[:group_name]).pluck(:id).first
list = list.joins("JOIN group_archived_messages gm ON gm.topic_id = topics.id AND
gm.group_id = #{group_id.to_i}")
create_list(:private_messages, {}, list) create_list(:private_messages, {}, list)
end end
@ -195,7 +228,9 @@ class TopicQuery
topics = yield(topics) if block_given? topics = yield(topics) if block_given?
options = options.merge(@options) options = options.merge(@options)
if ["activity","default"].include?(options[:order] || "activity") && !options[:unordered] if ["activity","default"].include?(options[:order] || "activity") &&
!options[:unordered] &&
filter != :private_messages
topics = prioritize_pinned_topics(topics, options) topics = prioritize_pinned_topics(topics, options)
end end

View File

@ -1,14 +1,17 @@
class TopicsBulkAction class TopicsBulkAction
def initialize(user, topic_ids, operation) def initialize(user, topic_ids, operation, options={})
@user = user @user = user
@topic_ids = topic_ids @topic_ids = topic_ids
@operation = operation @operation = operation
@changed_ids = [] @changed_ids = []
@options = options
end end
def self.operations def self.operations
@operations ||= %w(change_category close archive change_notification_level reset_read dismiss_posts delete unlist) @operations ||= %w(change_category close archive change_notification_level
reset_read dismiss_posts delete unlist archive_messages
move_messages_to_inbox)
end end
def self.register_operation(name, &block) def self.register_operation(name, &block)
@ -24,6 +27,43 @@ class TopicsBulkAction
private private
def find_group
return unless @options[:group]
group = Group.where('name ilike ?', @options[:group]).first
raise Discourse::InvalidParameters.new(:group) unless group
unless group.group_users.where(user_id: @user.id).exists?
raise Discourse::InvalidParameters.new(:group)
end
group
end
def move_messages_to_inbox
group = find_group
topics.each do |t|
if guardian.can_see?(t) && t.private_message?
if group
GroupArchivedMessage.where(group_id: group.id, topic_id: t.id).destroy_all
else
UserArchivedMessage.where(user_id: @user.id, topic_id: t.id).destroy_all
end
end
end
end
def archive_messages
group = find_group
topics.each do |t|
if guardian.can_see?(t) && t.private_message?
if group
GroupArchivedMessage.create!(group_id: group.id, topic_id: t.id)
else
UserArchivedMessage.create!(user_id: @user.id, topic_id: t.id)
end
end
end
end
def dismiss_posts def dismiss_posts
sql = " sql = "
UPDATE topic_users tu UPDATE topic_users tu

View File

@ -478,6 +478,9 @@ describe PostCreator do
expect(unrelated.notifications.count).to eq(0) expect(unrelated.notifications.count).to eq(0)
expect(post.topic.subtype).to eq(TopicSubtype.user_to_user) expect(post.topic.subtype).to eq(TopicSubtype.user_to_user)
# archive this message and ensure archive is cleared for all users on reply
UserArchivedMessage.create(user_id: target_user2.id, topic_id: post.topic_id)
# if an admin replies they should be added to the allowed user list # if an admin replies they should be added to the allowed user list
admin = Fabricate(:admin) admin = Fabricate(:admin)
PostCreator.create(admin, raw: 'hi there welcome topic, I am a mod', PostCreator.create(admin, raw: 'hi there welcome topic, I am a mod',
@ -485,6 +488,8 @@ describe PostCreator do
post.topic.reload post.topic.reload
expect(post.topic.topic_allowed_users.where(user_id: admin.id).count).to eq(1) expect(post.topic.topic_allowed_users.where(user_id: admin.id).count).to eq(1)
expect(UserArchivedMessage.where(user_id: target_user2.id, topic_id: post.topic_id).count).to eq(0)
end end
end end

View File

@ -1148,7 +1148,7 @@ describe TopicsController do
it "delegates work to `TopicsBulkAction`" do it "delegates work to `TopicsBulkAction`" do
topics_bulk_action = mock topics_bulk_action = mock
TopicsBulkAction.expects(:new).with(user, topic_ids, operation).returns(topics_bulk_action) TopicsBulkAction.expects(:new).with(user, topic_ids, operation, group: nil).returns(topics_bulk_action)
topics_bulk_action.expects(:perform!) topics_bulk_action.expects(:perform!)
xhr :put, :bulk, topic_ids: topic_ids, operation: operation xhr :put, :bulk, topic_ids: topic_ids, operation: operation
end end