Add "Unassign All" button to user's assigned topics view
This commit is contained in:
parent
7458b38f71
commit
754209ce58
|
@ -70,5 +70,11 @@ module DiscourseAssign
|
|||
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def unassign_all
|
||||
user = User.find_by(id: params[:user_id])
|
||||
TopicAssigner.unassign_all(user, current_user)
|
||||
render json: success_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
user: Ember.inject.controller(),
|
||||
|
||||
@computed('model.topics')
|
||||
canUnassignAll(topics) {
|
||||
return topics && topics.length && this.currentUser.get('staff');
|
||||
},
|
||||
|
||||
actions: {
|
||||
unassignAll() {
|
||||
let user = this.get('user.model');
|
||||
bootbox.confirm(
|
||||
I18n.t("discourse_assign.unassign_all.confirm", { username: user.get('username') }),
|
||||
value => {
|
||||
if (value) {
|
||||
ajax("/assign/unassign-all", {
|
||||
type: 'PUT',
|
||||
data: { user_id: user.get('id') }
|
||||
}).then(() => this.send('unassignedAll'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -3,7 +3,30 @@ import UserTopicListRoute from "discourse/routes/user-topic-list";
|
|||
export default UserTopicListRoute.extend({
|
||||
userActionType: 16,
|
||||
noContentHelpKey: "discourse_assigns.no_assigns",
|
||||
model: function() {
|
||||
return this.store.findFiltered('topicList', {filter: 'latest', params: {assigned: this.modelFor('user').get('username_lower') }});
|
||||
|
||||
model() {
|
||||
return this.store.findFiltered(
|
||||
'topicList',
|
||||
{
|
||||
filter: 'latest',
|
||||
params: { assigned: this.modelFor('user').get('username_lower') }
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
renderTemplate() {
|
||||
this.render('user-activity-assigned');
|
||||
this.render('user-topics-list', { into: 'user-activity-assigned' });
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
this._super(controller, model);
|
||||
controller.set('model', model);
|
||||
},
|
||||
|
||||
actions: {
|
||||
unassignedAll() {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{{#if canUnassignAll}}
|
||||
<div class='assign-controls'>
|
||||
{{d-button
|
||||
action=(action "unassignAll")
|
||||
icon="times"
|
||||
label="discourse_assign.unassign_all.title"
|
||||
class="btn-danger"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{outlet}}
|
|
@ -1,3 +1,11 @@
|
|||
.user-right {
|
||||
.assign-controls {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-to {
|
||||
.d-icon, i.fa {
|
||||
margin-right: 0.5em;
|
||||
|
|
|
@ -9,6 +9,10 @@ en:
|
|||
assigned: "Assigned"
|
||||
assigned_to: "Assigned to"
|
||||
assign_notification: "<i title='assigned' class='fa fa-user-plus'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||
unassign_all:
|
||||
title: "Unassign All Topics"
|
||||
confirm: "Are you sure you want to unassign all topics from {{username}}?"
|
||||
|
||||
unassign:
|
||||
title: "Unassign"
|
||||
help: "Unassign Topic"
|
||||
|
|
|
@ -2,5 +2,6 @@ DiscourseAssign::Engine.routes.draw do
|
|||
put "/claim/:topic_id" => "assign#claim"
|
||||
put "/assign" => "assign#assign"
|
||||
put "/unassign" => "assign#unassign"
|
||||
put "/unassign-all" => "assign#unassign_all"
|
||||
get "/suggestions" => "assign#suggestions"
|
||||
end
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
module Jobs
|
||||
class UnassignBulk < Jobs::Base
|
||||
def execute(args)
|
||||
assigned_by = User.find(args[:assigned_by_id])
|
||||
Topic.where(id: args[:topic_ids]).each do |t|
|
||||
TopicAssigner.new(t, assigned_by).unassign
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,25 @@
|
|||
require_dependency 'email/sender'
|
||||
|
||||
class ::TopicAssigner
|
||||
|
||||
def self.unassign_all(user, assigned_by)
|
||||
topic_ids = TopicCustomField.where(name: 'assigned_to_id', value: user.id).pluck(:topic_id)
|
||||
|
||||
# Fast path: by doing this we can instantly refresh for the user showing no assigned topics
|
||||
# while doing the "full" removal asynchronously.
|
||||
TopicCustomField.where(
|
||||
name: ['assigned_to_id', 'assigned_by_id'],
|
||||
topic_id: topic_ids
|
||||
).delete_all
|
||||
|
||||
Jobs.enqueue(
|
||||
:unassign_bulk,
|
||||
user_id: user.id,
|
||||
assigned_by_id: assigned_by.id,
|
||||
topic_ids: topic_ids
|
||||
)
|
||||
end
|
||||
|
||||
def self.backfill_auto_assign
|
||||
staff_mention = User.where('moderator OR admin')
|
||||
.pluck('username')
|
||||
|
@ -95,9 +114,7 @@ SQL
|
|||
end
|
||||
|
||||
def assign(assign_to, silent: false)
|
||||
@topic.custom_fields["assigned_to_id"] = assign_to.id
|
||||
@topic.custom_fields["assigned_by_id"] = @assigned_by.id
|
||||
@topic.save!
|
||||
@topic.upsert_custom_fields(assigned_to_id: assign_to.id, assigned_by_id: @assigned_by.id)
|
||||
|
||||
first_post = @topic.posts.find_by(post_number: 1)
|
||||
first_post.publish_change_to_clients!(:revised, reload_topic: true)
|
||||
|
@ -162,9 +179,7 @@ SQL
|
|||
|
||||
def unassign(silent: false)
|
||||
if assigned_to_id = @topic.custom_fields["assigned_to_id"]
|
||||
@topic.custom_fields["assigned_to_id"] = nil
|
||||
@topic.custom_fields["assigned_by_id"] = nil
|
||||
@topic.save!
|
||||
@topic.upsert_custom_fields(assigned_to_id: nil, assigned_by_id: nil)
|
||||
|
||||
post = @topic.posts.where(post_number: 1).first
|
||||
return unless post.present?
|
||||
|
|
|
@ -15,6 +15,7 @@ Discourse::Application.routes.append do
|
|||
end
|
||||
|
||||
after_initialize do
|
||||
require File.expand_path('../jobs/unassign_bulk', __FILE__)
|
||||
require 'topic_assigner'
|
||||
|
||||
# Raise an invalid access error if a user tries to act on something
|
||||
|
|
|
@ -22,4 +22,25 @@ RSpec.describe TopicAssigner do
|
|||
assert_publish_topic_state(pm, user) { assigner.unassign }
|
||||
end
|
||||
end
|
||||
|
||||
context "assigning and unassigning" do
|
||||
let(:post) { Fabricate(:post) }
|
||||
let(:topic) { post.topic }
|
||||
let(:moderator) { Fabricate(:moderator) }
|
||||
let(:assigner) { TopicAssigner.new(topic, moderator) }
|
||||
|
||||
it "can assign and unassign correctly" do
|
||||
assigner.assign(moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_present
|
||||
assigner.unassign
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_blank
|
||||
end
|
||||
|
||||
it "can unassign all a user's topics at once" do
|
||||
assigner.assign(moderator)
|
||||
TopicAssigner.unassign_all(moderator, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_blank
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue