DEV: Apply syntax_tree formatting
This commit is contained in:
parent
8c11d4d6ed
commit
6116f26642
2
Gemfile
2
Gemfile
|
@ -5,4 +5,4 @@ source "https://rubygems.org"
|
|||
group :development do
|
||||
gem "rubocop-discourse", git: "https://github.com/discourse/rubocop-discourse/", branch: "stree"
|
||||
gem "syntax_tree"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,9 +7,10 @@ module DiscourseAssign
|
|||
|
||||
def suggestions
|
||||
users = [current_user]
|
||||
users += User
|
||||
.where('users.id <> ?', current_user.id)
|
||||
.joins(<<~SQL
|
||||
users +=
|
||||
User
|
||||
.where("users.id <> ?", current_user.id)
|
||||
.joins(<<~SQL)
|
||||
JOIN(
|
||||
SELECT assigned_to_id user_id, MAX(created_at) last_assigned
|
||||
FROM assignments
|
||||
|
@ -18,16 +19,22 @@ module DiscourseAssign
|
|||
HAVING COUNT(*) < #{SiteSetting.max_assigned_topics}
|
||||
) as X ON X.user_id = users.id
|
||||
SQL
|
||||
)
|
||||
.assign_allowed
|
||||
.order('X.last_assigned DESC')
|
||||
.limit(6)
|
||||
.assign_allowed
|
||||
.order("X.last_assigned DESC")
|
||||
.limit(6)
|
||||
|
||||
render json: {
|
||||
assign_allowed_on_groups: Group.visible_groups(current_user).assign_allowed_groups.pluck(:name),
|
||||
assign_allowed_for_groups: Group.visible_groups(current_user).assignable(current_user).pluck(:name),
|
||||
suggestions: ActiveModel::ArraySerializer.new(users, scope: guardian, each_serializer: BasicUserSerializer),
|
||||
}
|
||||
assign_allowed_on_groups:
|
||||
Group.visible_groups(current_user).assign_allowed_groups.pluck(:name),
|
||||
assign_allowed_for_groups:
|
||||
Group.visible_groups(current_user).assignable(current_user).pluck(:name),
|
||||
suggestions:
|
||||
ActiveModel::ArraySerializer.new(
|
||||
users,
|
||||
scope: guardian,
|
||||
each_serializer: BasicUserSerializer,
|
||||
),
|
||||
}
|
||||
end
|
||||
|
||||
def unassign
|
||||
|
@ -46,11 +53,18 @@ module DiscourseAssign
|
|||
def assign
|
||||
target_id = params.require(:target_id)
|
||||
target_type = params.require(:target_type)
|
||||
username = params.permit(:username)['username']
|
||||
group_name = params.permit(:group_name)['group_name']
|
||||
note = params.permit(:note)['note'].presence
|
||||
username = params.permit(:username)["username"]
|
||||
group_name = params.permit(:group_name)["group_name"]
|
||||
note = params.permit(:note)["note"].presence
|
||||
|
||||
assign_to = username.present? ? User.find_by(username_lower: username.downcase) : Group.where("LOWER(name) = ?", group_name.downcase).first
|
||||
assign_to =
|
||||
(
|
||||
if username.present?
|
||||
User.find_by(username_lower: username.downcase)
|
||||
else
|
||||
Group.where("LOWER(name) = ?", group_name.downcase).first
|
||||
end
|
||||
)
|
||||
|
||||
raise Discourse::NotFound unless assign_to
|
||||
raise Discourse::NotFound if !Assignment.valid_type?(target_type)
|
||||
|
@ -72,23 +86,31 @@ module DiscourseAssign
|
|||
offset = (params[:offset] || 0).to_i
|
||||
limit = (params[:limit] || 100).to_i
|
||||
|
||||
topics = Topic
|
||||
.includes(:tags)
|
||||
.includes(:user)
|
||||
.joins("JOIN assignments a ON a.target_id = topics.id AND a.target_type = 'Topic' AND a.assigned_to_id IS NOT NULL")
|
||||
.order("a.assigned_to_id, topics.bumped_at desc")
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
topics =
|
||||
Topic
|
||||
.includes(:tags)
|
||||
.includes(:user)
|
||||
.joins(
|
||||
"JOIN assignments a ON a.target_id = topics.id AND a.target_type = 'Topic' AND a.assigned_to_id IS NOT NULL",
|
||||
)
|
||||
.order("a.assigned_to_id, topics.bumped_at desc")
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
|
||||
Topic.preload_custom_fields(topics, TopicList.preloaded_custom_fields)
|
||||
|
||||
topic_assignments = Assignment.where(target_id: topics.map(&:id), target_type: 'Topic', active: true).pluck(:target_id, :assigned_to_id).to_h
|
||||
topic_assignments =
|
||||
Assignment
|
||||
.where(target_id: topics.map(&:id), target_type: "Topic", active: true)
|
||||
.pluck(:target_id, :assigned_to_id)
|
||||
.to_h
|
||||
|
||||
users = User
|
||||
.where("users.id IN (?)", topic_assignments.values.uniq)
|
||||
.joins("join user_emails on user_emails.user_id = users.id AND user_emails.primary")
|
||||
.select(UserLookup.lookup_columns)
|
||||
.to_a
|
||||
users =
|
||||
User
|
||||
.where("users.id IN (?)", topic_assignments.values.uniq)
|
||||
.joins("join user_emails on user_emails.user_id = users.id AND user_emails.primary")
|
||||
.select(UserLookup.lookup_columns)
|
||||
.to_a
|
||||
|
||||
User.preload_custom_fields(users, User.allowed_user_custom_fields(guardian))
|
||||
|
||||
|
@ -114,41 +136,41 @@ module DiscourseAssign
|
|||
|
||||
guardian.ensure_can_see_group_members!(group)
|
||||
|
||||
members = User
|
||||
.joins("LEFT OUTER JOIN group_users g ON g.user_id = users.id")
|
||||
.joins("LEFT OUTER JOIN assignments a ON a.assigned_to_id = users.id AND a.assigned_to_type = 'User'")
|
||||
.joins("LEFT OUTER JOIN topics t ON t.id = a.target_id AND a.target_type = 'Topic'")
|
||||
.where("g.group_id = ? AND users.id > 0 AND t.deleted_at IS NULL", group.id)
|
||||
.where("a.assigned_to_id IS NOT NULL AND a.active")
|
||||
.order('COUNT(users.id) DESC')
|
||||
.group('users.id')
|
||||
.select('users.*, COUNT(users.id) as "assignments_count"')
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
members =
|
||||
User
|
||||
.joins("LEFT OUTER JOIN group_users g ON g.user_id = users.id")
|
||||
.joins(
|
||||
"LEFT OUTER JOIN assignments a ON a.assigned_to_id = users.id AND a.assigned_to_type = 'User'",
|
||||
)
|
||||
.joins("LEFT OUTER JOIN topics t ON t.id = a.target_id AND a.target_type = 'Topic'")
|
||||
.where("g.group_id = ? AND users.id > 0 AND t.deleted_at IS NULL", group.id)
|
||||
.where("a.assigned_to_id IS NOT NULL AND a.active")
|
||||
.order("COUNT(users.id) DESC")
|
||||
.group("users.id")
|
||||
.select('users.*, COUNT(users.id) as "assignments_count"')
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
|
||||
if params[:filter]
|
||||
members = members.where(<<~SQL, pattern: "%#{params[:filter]}%")
|
||||
members = members.where(<<~SQL, pattern: "%#{params[:filter]}%") if params[:filter]
|
||||
users.name ILIKE :pattern OR users.username_lower ILIKE :pattern
|
||||
SQL
|
||||
end
|
||||
|
||||
group_assignments = Topic
|
||||
.joins("JOIN assignments a ON a.topic_id = topics.id")
|
||||
.where(<<~SQL, group_id: group.id)
|
||||
group_assignments =
|
||||
Topic
|
||||
.joins("JOIN assignments a ON a.topic_id = topics.id")
|
||||
.where(<<~SQL, group_id: group.id)
|
||||
a.assigned_to_id = :group_id AND a.assigned_to_type = 'Group' AND a.active
|
||||
SQL
|
||||
.pluck(:topic_id)
|
||||
.pluck(:topic_id)
|
||||
|
||||
assignments = TopicQuery
|
||||
.new(current_user)
|
||||
.group_topics_assigned_results(group)
|
||||
.pluck('topics.id')
|
||||
assignments =
|
||||
TopicQuery.new(current_user).group_topics_assigned_results(group).pluck("topics.id")
|
||||
|
||||
render json: {
|
||||
members: serialize_data(members, GroupUserAssignedSerializer),
|
||||
assignment_count: (assignments | group_assignments).count,
|
||||
group_assignment_count: group_assignments.count
|
||||
}
|
||||
members: serialize_data(members, GroupUserAssignedSerializer),
|
||||
assignment_count: (assignments | group_assignments).count,
|
||||
group_assignment_count: group_assignments.count,
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -156,26 +178,59 @@ module DiscourseAssign
|
|||
def translate_failure(reason, assign_to)
|
||||
case reason
|
||||
when :already_assigned
|
||||
{ error: I18n.t('discourse_assign.already_assigned', username: assign_to.username) }
|
||||
{ error: I18n.t("discourse_assign.already_assigned", username: assign_to.username) }
|
||||
when :forbidden_assign_to
|
||||
{ error: I18n.t('discourse_assign.forbidden_assign_to', username: assign_to.username) }
|
||||
{ error: I18n.t("discourse_assign.forbidden_assign_to", username: assign_to.username) }
|
||||
when :forbidden_assignee_not_pm_participant
|
||||
{ error: I18n.t('discourse_assign.forbidden_assignee_not_pm_participant', username: assign_to.username) }
|
||||
{
|
||||
error:
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_assignee_not_pm_participant",
|
||||
username: assign_to.username,
|
||||
),
|
||||
}
|
||||
when :forbidden_assignee_cant_see_topic
|
||||
{ error: I18n.t('discourse_assign.forbidden_assignee_cant_see_topic', username: assign_to.username) }
|
||||
{
|
||||
error:
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_assignee_cant_see_topic",
|
||||
username: assign_to.username,
|
||||
),
|
||||
}
|
||||
when :group_already_assigned
|
||||
{ error: I18n.t('discourse_assign.group_already_assigned', group: assign_to.name) }
|
||||
{ error: I18n.t("discourse_assign.group_already_assigned", group: assign_to.name) }
|
||||
when :forbidden_group_assign_to
|
||||
{ error: I18n.t('discourse_assign.forbidden_group_assign_to', group: assign_to.name) }
|
||||
{ error: I18n.t("discourse_assign.forbidden_group_assign_to", group: assign_to.name) }
|
||||
when :forbidden_group_assignee_not_pm_participant
|
||||
{ error: I18n.t('discourse_assign.forbidden_group_assignee_not_pm_participant', group: assign_to.name) }
|
||||
{
|
||||
error:
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_group_assignee_not_pm_participant",
|
||||
group: assign_to.name,
|
||||
),
|
||||
}
|
||||
when :forbidden_group_assignee_cant_see_topic
|
||||
{ error: I18n.t('discourse_assign.forbidden_group_assignee_cant_see_topic', group: assign_to.name) }
|
||||
{
|
||||
error:
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_group_assignee_cant_see_topic",
|
||||
group: assign_to.name,
|
||||
),
|
||||
}
|
||||
when :too_many_assigns_for_topic
|
||||
{ error: I18n.t('discourse_assign.too_many_assigns_for_topic', limit: Assigner::ASSIGNMENTS_PER_TOPIC_LIMIT) }
|
||||
{
|
||||
error:
|
||||
I18n.t(
|
||||
"discourse_assign.too_many_assigns_for_topic",
|
||||
limit: Assigner::ASSIGNMENTS_PER_TOPIC_LIMIT,
|
||||
),
|
||||
}
|
||||
else
|
||||
max = SiteSetting.max_assigned_topics
|
||||
{ error: I18n.t('discourse_assign.too_many_assigns', username: assign_to.username, max: max) }
|
||||
{
|
||||
error:
|
||||
I18n.t("discourse_assign.too_many_assigns", username: assign_to.username, max: max),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'email/message_builder'
|
||||
require_dependency "email/message_builder"
|
||||
|
||||
class AssignMailer < ActionMailer::Base
|
||||
include Email::BuildEmailHelper
|
||||
|
||||
def self.levels
|
||||
@levels ||= Enum.new(never: 'never',
|
||||
different_users: 'different_users',
|
||||
always: 'always')
|
||||
@levels ||= Enum.new(never: "never", different_users: "different_users", always: "always")
|
||||
end
|
||||
|
||||
def send_assignment(to_address, topic, assigned_by)
|
||||
opts = {
|
||||
template: 'assign_mailer',
|
||||
template: "assign_mailer",
|
||||
topic_title: topic.title,
|
||||
assignee_name: assigned_by.username,
|
||||
topic_excerpt: topic.excerpt,
|
||||
topic_link: topic.url
|
||||
topic_link: topic.url,
|
||||
}
|
||||
build_email(to_address, opts)
|
||||
end
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'enum_site_setting'
|
||||
require_dependency "enum_site_setting"
|
||||
|
||||
class AssignMailerSiteSettings < EnumSiteSetting
|
||||
|
||||
def self.valid_value?(val)
|
||||
values.any? { |v| v[:value].to_s == val.to_s }
|
||||
end
|
||||
|
||||
def self.values
|
||||
@values ||= [
|
||||
{ name: 'discourse_assign.assign_mailer.never', value: AssignMailer.levels[:never] },
|
||||
{ name: 'discourse_assign.assign_mailer.different_users', value: AssignMailer.levels[:different_users] },
|
||||
{ name: 'discourse_assign.assign_mailer.always', value: AssignMailer.levels[:always] }
|
||||
{ name: "discourse_assign.assign_mailer.never", value: AssignMailer.levels[:never] },
|
||||
{
|
||||
name: "discourse_assign.assign_mailer.different_users",
|
||||
value: AssignMailer.levels[:different_users],
|
||||
},
|
||||
{ name: "discourse_assign.assign_mailer.always", value: AssignMailer.levels[:always] },
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Assignment < ActiveRecord::Base
|
||||
VALID_TYPES = %w(topic post).freeze
|
||||
VALID_TYPES = %w[topic post].freeze
|
||||
|
||||
belongs_to :topic
|
||||
belongs_to :assigned_to, polymorphic: true
|
||||
belongs_to :assigned_by_user, class_name: "User"
|
||||
belongs_to :target, polymorphic: true
|
||||
|
||||
scope :joins_with_topics, -> { joins("INNER JOIN topics ON topics.id = assignments.target_id AND assignments.target_type = 'Topic' AND topics.deleted_at IS NULL") }
|
||||
scope :joins_with_topics,
|
||||
-> {
|
||||
joins(
|
||||
"INNER JOIN topics ON topics.id = assignments.target_id AND assignments.target_type = 'Topic' AND topics.deleted_at IS NULL",
|
||||
)
|
||||
}
|
||||
|
||||
def self.valid_type?(type)
|
||||
VALID_TYPES.include?(type.downcase)
|
||||
end
|
||||
|
||||
def assigned_to_user?
|
||||
assigned_to_type == 'User'
|
||||
assigned_to_type == "User"
|
||||
end
|
||||
|
||||
def assigned_to_group?
|
||||
assigned_to_type == 'Group'
|
||||
assigned_to_type == "Group"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'enum_site_setting'
|
||||
require_dependency "enum_site_setting"
|
||||
|
||||
class RemindAssignsFrequencySiteSettings < EnumSiteSetting
|
||||
|
||||
def self.valid_value?(val)
|
||||
val.to_i.to_s == val.to_s &&
|
||||
values.any? { |v| v[:value] == val.to_i }
|
||||
val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
|
||||
end
|
||||
|
||||
DAILY_MINUTES = 24 * 60 * 1
|
||||
|
@ -16,25 +14,11 @@ class RemindAssignsFrequencySiteSettings < EnumSiteSetting
|
|||
|
||||
def self.values
|
||||
@values ||= [
|
||||
{
|
||||
name: 'discourse_assign.reminders_frequency.never', value: 0
|
||||
},
|
||||
{
|
||||
name: 'discourse_assign.reminders_frequency.daily',
|
||||
value: DAILY_MINUTES
|
||||
},
|
||||
{
|
||||
name: 'discourse_assign.reminders_frequency.weekly',
|
||||
value: WEEKLY_MINUTES
|
||||
},
|
||||
{
|
||||
name: 'discourse_assign.reminders_frequency.monthly',
|
||||
value: MONTHLY_MINUTES
|
||||
},
|
||||
{
|
||||
name: 'discourse_assign.reminders_frequency.quarterly',
|
||||
value: QUARTERLY_MINUTES
|
||||
}
|
||||
{ name: "discourse_assign.reminders_frequency.never", value: 0 },
|
||||
{ name: "discourse_assign.reminders_frequency.daily", value: DAILY_MINUTES },
|
||||
{ name: "discourse_assign.reminders_frequency.weekly", value: WEEKLY_MINUTES },
|
||||
{ name: "discourse_assign.reminders_frequency.monthly", value: MONTHLY_MINUTES },
|
||||
{ name: "discourse_assign.reminders_frequency.quarterly", value: QUARTERLY_MINUTES },
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -45,7 +29,7 @@ class RemindAssignsFrequencySiteSettings < EnumSiteSetting
|
|||
def self.frequency_for(minutes)
|
||||
value = values.detect { |v| v[:value] == minutes }
|
||||
|
||||
raise Discourse::InvalidParameters(:task_reminders_frequency) if value.nil?
|
||||
raise Discourse.InvalidParameters(:task_reminders_frequency) if value.nil?
|
||||
|
||||
I18n.t(value[:name])
|
||||
end
|
||||
|
|
|
@ -3,12 +3,7 @@
|
|||
class AssignedTopicSerializer < BasicTopicSerializer
|
||||
include TopicTagsMixin
|
||||
|
||||
attributes :excerpt,
|
||||
:category_id,
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:assigned_to_user,
|
||||
:assigned_to_group
|
||||
attributes :excerpt, :category_id, :created_at, :updated_at, :assigned_to_user, :assigned_to_group
|
||||
|
||||
has_one :user, serializer: BasicUserSerializer, embed: :objects
|
||||
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GroupUserAssignedSerializer < BasicUserSerializer
|
||||
|
||||
attributes :assignments_count,
|
||||
:username_lower
|
||||
attributes :assignments_count, :username_lower
|
||||
|
||||
def include_assignments_count
|
||||
object.can_assign?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
class AddLastRemindedAtIndex < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :user_custom_fields, %i[name user_id], name: :idx_user_custom_fields_last_reminded_at,
|
||||
unique: true, where: "name = 'last_reminded_at'"
|
||||
add_index :user_custom_fields,
|
||||
%i[name user_id],
|
||||
name: :idx_user_custom_fields_last_reminded_at,
|
||||
unique: true,
|
||||
where: "name = 'last_reminded_at'"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
class AddRemindsAssignFrequencyIndex < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :user_custom_fields, %i[name user_id], name: :idx_user_custom_fields_remind_assigns_frequency,
|
||||
unique: true, where: "name = 'remind_assigns_frequency'"
|
||||
add_index :user_custom_fields,
|
||||
%i[name user_id],
|
||||
name: :idx_user_custom_fields_remind_assigns_frequency,
|
||||
unique: true,
|
||||
where: "name = 'remind_assigns_frequency'"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,15 +2,19 @@
|
|||
|
||||
class SetAssignAllowedOnGroupsDefault < ActiveRecord::Migration[5.2]
|
||||
def up
|
||||
current_values = DB.query_single("SELECT value FROM site_settings WHERE name = 'assign_allowed_on_groups'").first
|
||||
current_values =
|
||||
DB.query_single(
|
||||
"SELECT value FROM site_settings WHERE name = 'assign_allowed_on_groups'",
|
||||
).first
|
||||
|
||||
# Dynamically sets the default value, supports older versions.
|
||||
if current_values.nil?
|
||||
min_version = 201_907_171_337_43
|
||||
migrated_site_setting = DB.query_single(
|
||||
"SELECT schema_migrations.version FROM schema_migrations WHERE schema_migrations.version = '#{min_version}'"
|
||||
).first
|
||||
default = migrated_site_setting.present? ? Group::AUTO_GROUPS[:staff] : 'staff'
|
||||
migrated_site_setting =
|
||||
DB.query_single(
|
||||
"SELECT schema_migrations.version FROM schema_migrations WHERE schema_migrations.version = '#{min_version}'",
|
||||
).first
|
||||
default = migrated_site_setting.present? ? Group::AUTO_GROUPS[:staff] : "staff"
|
||||
|
||||
execute "INSERT INTO site_settings (name, data_type, value, created_at, updated_at)
|
||||
VALUES ('assign_allowed_on_groups', #{SiteSettings::TypeSupervisor.types[:group_list]}, '#{default}', now(), now())"
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
class AddIndexToAssignedToIdAndType < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_index :assignments, [:assigned_to_id, :assigned_to_type]
|
||||
add_index :assignments, %i[assigned_to_id assigned_to_type]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,8 +14,11 @@ class AddTargetToAssignments < ActiveRecord::Migration[6.1]
|
|||
change_column :assignments, :target_id, :integer, null: false
|
||||
change_column :assignments, :target_type, :string, null: false
|
||||
|
||||
add_index :assignments, [:target_id, :target_type], unique: true
|
||||
add_index :assignments, [:assigned_to_id, :assigned_to_type, :target_id, :target_type], unique: true, name: 'unique_target_and_assigned'
|
||||
add_index :assignments, %i[target_id target_type], unique: true
|
||||
add_index :assignments,
|
||||
%i[assigned_to_id assigned_to_type target_id target_type],
|
||||
unique: true,
|
||||
name: "unique_target_and_assigned"
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -41,7 +41,6 @@ class CorrectlyMoveAssignmentsFromCustomFieldsToATable < ActiveRecord::Migration
|
|||
ORDER BY assigned_by.created_at DESC
|
||||
ON CONFLICT DO NOTHING
|
||||
SQL
|
||||
|
||||
else
|
||||
execute <<~SQL
|
||||
INSERT INTO assignments (assigned_to_id, assigned_by_user_id, topic_id, created_at, updated_at)
|
||||
|
|
|
@ -8,12 +8,21 @@ module Jobs
|
|||
raise Discourse::InvalidParameters.new(:assigned_to_id) if args[:assigned_to_id].nil?
|
||||
raise Discourse::InvalidParameters.new(:assigned_to_type) if args[:assigned_to_type].nil?
|
||||
raise Discourse::InvalidParameters.new(:assigned_by_id) if args[:assigned_by_id].nil?
|
||||
raise Discourse::InvalidParameters.new(:skip_small_action_post) if args[:skip_small_action_post].nil?
|
||||
if args[:skip_small_action_post].nil?
|
||||
raise Discourse::InvalidParameters.new(:skip_small_action_post)
|
||||
end
|
||||
|
||||
topic = Topic.find(args[:topic_id])
|
||||
post = Post.find(args[:post_id])
|
||||
assigned_by = User.find(args[:assigned_by_id])
|
||||
assigned_to = args[:assigned_to_type] == "User" ? User.find(args[:assigned_to_id]) : Group.find(args[:assigned_to_id])
|
||||
assigned_to =
|
||||
(
|
||||
if args[:assigned_to_type] == "User"
|
||||
User.find(args[:assigned_to_id])
|
||||
else
|
||||
Group.find(args[:assigned_to_id])
|
||||
end
|
||||
)
|
||||
assigned_to_users = args[:assigned_to_type] == "User" ? [assigned_to] : assigned_to.users
|
||||
|
||||
assigned_to_users.each do |user|
|
||||
|
@ -29,12 +38,18 @@ module Jobs
|
|||
username: assigned_by.username,
|
||||
notification_type: Notification.types[:assigned] || Notification.types[:custom],
|
||||
excerpt:
|
||||
I18n.t(
|
||||
(assigned_to_user ? "discourse_assign.topic_assigned_excerpt" : "discourse_assign.topic_group_assigned_excerpt"),
|
||||
title: topic.title,
|
||||
group: assigned_to.name,
|
||||
locale: user.effective_locale
|
||||
)
|
||||
I18n.t(
|
||||
(
|
||||
if assigned_to_user
|
||||
"discourse_assign.topic_assigned_excerpt"
|
||||
else
|
||||
"discourse_assign.topic_group_assigned_excerpt"
|
||||
end
|
||||
),
|
||||
title: topic.title,
|
||||
group: assigned_to.name,
|
||||
locale: user.effective_locale,
|
||||
),
|
||||
)
|
||||
|
||||
next if args[:skip_small_action_post]
|
||||
|
@ -45,10 +60,17 @@ module Jobs
|
|||
post_number: post.post_number,
|
||||
high_priority: true,
|
||||
data: {
|
||||
message: assigned_to_user ? 'discourse_assign.assign_notification' : 'discourse_assign.assign_group_notification',
|
||||
message:
|
||||
(
|
||||
if assigned_to_user
|
||||
"discourse_assign.assign_notification"
|
||||
else
|
||||
"discourse_assign.assign_group_notification"
|
||||
end
|
||||
),
|
||||
display_username: assigned_to_user ? assigned_by.username : assigned_to.name,
|
||||
topic_title: topic.title
|
||||
}.to_json
|
||||
topic_title: topic.title,
|
||||
}.to_json,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Jobs
|
||||
class RemindUser < ::Jobs::Base
|
||||
sidekiq_options queue: 'low'
|
||||
sidekiq_options queue: "low"
|
||||
|
||||
def execute(args)
|
||||
user = User.find_by(id: args[:user_id])
|
||||
|
|
|
@ -8,16 +8,28 @@ module Jobs
|
|||
raise Discourse::InvalidParameters.new(:assigned_to_type) if args[:assigned_to_type].nil?
|
||||
|
||||
topic = Topic.find(args[:topic_id])
|
||||
assigned_to_users = args[:assigned_to_type] == "User" ? [User.find(args[:assigned_to_id])] : Group.find(args[:assigned_to_id]).users
|
||||
assigned_to_users =
|
||||
(
|
||||
if args[:assigned_to_type] == "User"
|
||||
[User.find(args[:assigned_to_id])]
|
||||
else
|
||||
Group.find(args[:assigned_to_id]).users
|
||||
end
|
||||
)
|
||||
|
||||
assigned_to_users.each do |user|
|
||||
Assigner.publish_topic_tracking_state(topic, user.id)
|
||||
|
||||
Notification.where(
|
||||
notification_type: Notification.types[:assigned] || Notification.types[:custom],
|
||||
user_id: user.id,
|
||||
topic_id: topic.id,
|
||||
).where("data like '%discourse_assign.assign_notification%' OR data like '%discourse_assign.assign_group_notification%'").destroy_all
|
||||
Notification
|
||||
.where(
|
||||
notification_type: Notification.types[:assigned] || Notification.types[:custom],
|
||||
user_id: user.id,
|
||||
topic_id: topic.id,
|
||||
)
|
||||
.where(
|
||||
"data like '%discourse_assign.assign_notification%' OR data like '%discourse_assign.assign_group_notification%'",
|
||||
)
|
||||
.destroy_all
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,18 +12,22 @@ module Jobs
|
|||
private
|
||||
|
||||
def skip_enqueue?
|
||||
SiteSetting.remind_assigns_frequency.nil? || !SiteSetting.assign_enabled? || SiteSetting.assign_allowed_on_groups.blank?
|
||||
SiteSetting.remind_assigns_frequency.nil? || !SiteSetting.assign_enabled? ||
|
||||
SiteSetting.assign_allowed_on_groups.blank?
|
||||
end
|
||||
|
||||
def allowed_group_ids
|
||||
Group.assign_allowed_groups.pluck(:id).join(',')
|
||||
Group.assign_allowed_groups.pluck(:id).join(",")
|
||||
end
|
||||
|
||||
def user_ids
|
||||
global_frequency = SiteSetting.remind_assigns_frequency
|
||||
frequency = ActiveRecord::Base.sanitize_sql("COALESCE(user_frequency.value, '#{global_frequency}')::INT")
|
||||
frequency =
|
||||
ActiveRecord::Base.sanitize_sql(
|
||||
"COALESCE(user_frequency.value, '#{global_frequency}')::INT",
|
||||
)
|
||||
|
||||
DB.query_single(<<~SQL
|
||||
DB.query_single(<<~SQL)
|
||||
SELECT assignments.assigned_to_id
|
||||
FROM assignments
|
||||
|
||||
|
@ -50,7 +54,6 @@ module Jobs
|
|||
GROUP BY assignments.assigned_to_id
|
||||
HAVING COUNT(assignments.assigned_to_id) > 1
|
||||
SQL
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
211
lib/assigner.rb
211
lib/assigner.rb
|
@ -1,17 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'email/sender'
|
||||
require 'nokogiri'
|
||||
require "email/sender"
|
||||
require "nokogiri"
|
||||
|
||||
class ::Assigner
|
||||
ASSIGNMENTS_PER_TOPIC_LIMIT = 5
|
||||
|
||||
def self.backfill_auto_assign
|
||||
staff_mention = User
|
||||
.assign_allowed
|
||||
.pluck('username')
|
||||
.map { |name| "p.cooked ILIKE '%mention%@#{name}%'" }
|
||||
.join(' OR ')
|
||||
staff_mention =
|
||||
User
|
||||
.assign_allowed
|
||||
.pluck("username")
|
||||
.map { |name| "p.cooked ILIKE '%mention%@#{name}%'" }
|
||||
.join(" OR ")
|
||||
|
||||
sql = <<~SQL
|
||||
SELECT p.topic_id, MAX(post_number) post_number
|
||||
|
@ -29,11 +30,16 @@ class ::Assigner
|
|||
puts
|
||||
assigned = 0
|
||||
|
||||
ActiveRecord::Base.connection.raw_connection.exec(sql).to_a.each do |row|
|
||||
post = Post.find_by(post_number: row["post_number"].to_i, topic_id: row["topic_id"].to_i)
|
||||
assigned += 1 if post && auto_assign(post)
|
||||
putc "."
|
||||
end
|
||||
ActiveRecord::Base
|
||||
.connection
|
||||
.raw_connection
|
||||
.exec(sql)
|
||||
.to_a
|
||||
.each do |row|
|
||||
post = Post.find_by(post_number: row["post_number"].to_i, topic_id: row["topic_id"].to_i)
|
||||
assigned += 1 if post && auto_assign(post)
|
||||
putc "."
|
||||
end
|
||||
|
||||
puts
|
||||
puts "#{assigned} topics where automatically assigned to staff members"
|
||||
|
@ -41,13 +47,23 @@ class ::Assigner
|
|||
|
||||
def self.assigned_self?(text)
|
||||
return false if text.blank? || SiteSetting.assign_self_regex.blank?
|
||||
regex = Regexp.new(SiteSetting.assign_self_regex) rescue nil
|
||||
regex =
|
||||
begin
|
||||
Regexp.new(SiteSetting.assign_self_regex)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
!!(regex && text[regex])
|
||||
end
|
||||
|
||||
def self.assigned_other?(text)
|
||||
return false if text.blank? || SiteSetting.assign_other_regex.blank?
|
||||
regex = Regexp.new(SiteSetting.assign_other_regex) rescue nil
|
||||
regex =
|
||||
begin
|
||||
Regexp.new(SiteSetting.assign_other_regex)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
!!(regex && text[regex])
|
||||
end
|
||||
|
||||
|
@ -78,7 +94,7 @@ class ::Assigner
|
|||
end
|
||||
|
||||
def self.is_last_staff_post?(post)
|
||||
allowed_user_ids = User.assign_allowed.pluck(:id).join(',')
|
||||
allowed_user_ids = User.assign_allowed.pluck(:id).join(",")
|
||||
|
||||
sql = <<~SQL
|
||||
SELECT 1
|
||||
|
@ -90,10 +106,7 @@ class ::Assigner
|
|||
HAVING MAX(post_number) = :post_number
|
||||
SQL
|
||||
|
||||
args = {
|
||||
topic_id: post.topic_id,
|
||||
post_number: post.post_number
|
||||
}
|
||||
args = { topic_id: post.topic_id, post_number: post.post_number }
|
||||
|
||||
DB.exec(sql, args) == 1
|
||||
end
|
||||
|
@ -101,20 +114,13 @@ class ::Assigner
|
|||
def self.mentioned_staff(post)
|
||||
mentions = post.raw_mentions
|
||||
if mentions.present?
|
||||
User.human_users
|
||||
.assign_allowed
|
||||
.where('username_lower IN (?)', mentions.map(&:downcase))
|
||||
.first
|
||||
User.human_users.assign_allowed.where("username_lower IN (?)", mentions.map(&:downcase)).first
|
||||
end
|
||||
end
|
||||
|
||||
def self.publish_topic_tracking_state(topic, user_id)
|
||||
if topic.private_message?
|
||||
MessageBus.publish(
|
||||
"/private-messages/assigned",
|
||||
{ topic_id: topic.id },
|
||||
user_ids: [user_id]
|
||||
)
|
||||
MessageBus.publish("/private-messages/assigned", { topic_id: topic.id }, user_ids: [user_id])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -135,11 +141,12 @@ class ::Assigner
|
|||
return true if assign_to.is_a?(Group)
|
||||
return true if @assigned_by.id == assign_to.id
|
||||
|
||||
assigned_total = Assignment
|
||||
.joins_with_topics
|
||||
.where(topics: { deleted_at: nil })
|
||||
.where(assigned_to_id: assign_to.id, active: true)
|
||||
.count
|
||||
assigned_total =
|
||||
Assignment
|
||||
.joins_with_topics
|
||||
.where(topics: { deleted_at: nil })
|
||||
.where(assigned_to_id: assign_to.id, active: true)
|
||||
.count
|
||||
|
||||
assigned_total < SiteSetting.max_assigned_topics
|
||||
end
|
||||
|
@ -165,7 +172,10 @@ class ::Assigner
|
|||
end
|
||||
|
||||
def can_assignee_see_target?(assignee)
|
||||
return false if (topic_target? || post_target?) && topic.private_message? && !private_message_allowed_user_ids.include?(assignee.id)
|
||||
if (topic_target? || post_target?) && topic.private_message? &&
|
||||
!private_message_allowed_user_ids.include?(assignee.id)
|
||||
return false
|
||||
end
|
||||
return Guardian.new(assignee).can_see_topic?(@target) if topic_target?
|
||||
return Guardian.new(assignee).can_see_post?(@target) if post_target?
|
||||
|
||||
|
@ -188,9 +198,17 @@ class ::Assigner
|
|||
def forbidden_reasons(assign_to:, type:, note:)
|
||||
case
|
||||
when assign_to.is_a?(User) && !can_assignee_see_target?(assign_to)
|
||||
topic.private_message? ? :forbidden_assignee_not_pm_participant : :forbidden_assignee_cant_see_topic
|
||||
if topic.private_message?
|
||||
:forbidden_assignee_not_pm_participant
|
||||
else
|
||||
:forbidden_assignee_cant_see_topic
|
||||
end
|
||||
when assign_to.is_a?(Group) && assign_to.users.any? { |user| !can_assignee_see_target?(user) }
|
||||
topic.private_message? ? :forbidden_group_assignee_not_pm_participant : :forbidden_group_assignee_cant_see_topic
|
||||
if topic.private_message?
|
||||
:forbidden_group_assignee_not_pm_participant
|
||||
else
|
||||
:forbidden_group_assignee_cant_see_topic
|
||||
end
|
||||
when !can_be_assigned?(assign_to)
|
||||
assign_to.is_a?(User) ? :forbidden_assign_to : :forbidden_group_assign_to
|
||||
when topic_same_assignee_and_note(assign_to, type, note)
|
||||
|
@ -240,7 +258,14 @@ class ::Assigner
|
|||
|
||||
@target.assignment&.destroy!
|
||||
|
||||
assignment = @target.create_assignment!(assigned_to_id: assign_to.id, assigned_to_type: assigned_to_type, assigned_by_user_id: @assigned_by.id, topic_id: topic.id, note: note)
|
||||
assignment =
|
||||
@target.create_assignment!(
|
||||
assigned_to_id: assign_to.id,
|
||||
assigned_to_type: assigned_to_type,
|
||||
assigned_by_user_id: @assigned_by.id,
|
||||
topic_id: topic.id,
|
||||
note: note,
|
||||
)
|
||||
|
||||
first_post.publish_change_to_clients!(:revised, reload_topic: true)
|
||||
|
||||
|
@ -250,19 +275,23 @@ class ::Assigner
|
|||
|
||||
if assignment.assigned_to_user?
|
||||
if !TopicUser.exists?(
|
||||
user_id: assign_to.id,
|
||||
topic_id: topic.id,
|
||||
notification_level: TopicUser.notification_levels[:watching]
|
||||
)
|
||||
user_id: assign_to.id,
|
||||
topic_id: topic.id,
|
||||
notification_level: TopicUser.notification_levels[:watching],
|
||||
)
|
||||
TopicUser.change(
|
||||
assign_to.id,
|
||||
topic.id,
|
||||
notification_level: TopicUser.notification_levels[:watching],
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed]
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed],
|
||||
)
|
||||
end
|
||||
|
||||
if SiteSetting.assign_mailer == AssignMailer.levels[:always] || (SiteSetting.assign_mailer == AssignMailer.levels[:different_users] && @assigned_by.id != assign_to.id)
|
||||
if SiteSetting.assign_mailer == AssignMailer.levels[:always] ||
|
||||
(
|
||||
SiteSetting.assign_mailer == AssignMailer.levels[:different_users] &&
|
||||
@assigned_by.id != assign_to.id
|
||||
)
|
||||
if !topic.muted?(assign_to)
|
||||
message = AssignMailer.send_assignment(assign_to.email, topic, @assigned_by)
|
||||
Email::Sender.new(message, :assign_message).send
|
||||
|
@ -283,18 +312,14 @@ class ::Assigner
|
|||
topic_id: topic.id,
|
||||
topic_title: topic.title,
|
||||
assigned_by_id: @assigned_by.id,
|
||||
assigned_by_username: @assigned_by.username
|
||||
assigned_by_username: @assigned_by.username,
|
||||
}
|
||||
if assignment.assigned_to_user?
|
||||
payload.merge!({
|
||||
assigned_to_id: assign_to.id,
|
||||
assigned_to_username: assign_to.username,
|
||||
})
|
||||
payload.merge!({ assigned_to_id: assign_to.id, assigned_to_username: assign_to.username })
|
||||
else
|
||||
payload.merge!({
|
||||
assigned_to_group_id: assign_to.id,
|
||||
assigned_to_group_name: assign_to.name,
|
||||
})
|
||||
payload.merge!(
|
||||
{ assigned_to_group_id: assign_to.id, assigned_to_group_name: assign_to.name },
|
||||
)
|
||||
end
|
||||
WebHook.enqueue_assign_hooks(assigned_to_type, payload.to_json)
|
||||
end
|
||||
|
@ -310,24 +335,25 @@ class ::Assigner
|
|||
|
||||
first_post.publish_change_to_clients!(:revised, reload_topic: true)
|
||||
|
||||
Jobs.enqueue(:unassign_notification,
|
||||
topic_id: topic.id,
|
||||
assigned_to_id: assignment.assigned_to.id,
|
||||
assigned_to_type: assignment.assigned_to_type)
|
||||
Jobs.enqueue(
|
||||
:unassign_notification,
|
||||
topic_id: topic.id,
|
||||
assigned_to_id: assignment.assigned_to.id,
|
||||
assigned_to_type: assignment.assigned_to_type,
|
||||
)
|
||||
|
||||
if assignment.assigned_to_user?
|
||||
if TopicUser.exists?(
|
||||
user_id: assignment.assigned_to_id,
|
||||
topic: topic,
|
||||
notification_level: TopicUser.notification_levels[:watching],
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed]
|
||||
)
|
||||
|
||||
user_id: assignment.assigned_to_id,
|
||||
topic: topic,
|
||||
notification_level: TopicUser.notification_levels[:watching],
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed],
|
||||
)
|
||||
TopicUser.change(
|
||||
assignment.assigned_to_id,
|
||||
topic.id,
|
||||
notification_level: TopicUser.notification_levels[:tracking],
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed]
|
||||
notifications_reason_id: TopicUser.notification_reasons[:plugin_changed],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -337,7 +363,9 @@ class ::Assigner
|
|||
if SiteSetting.unassign_creates_tracking_post && !silent
|
||||
post_type = SiteSetting.assigns_public ? Post.types[:small_action] : Post.types[:whisper]
|
||||
|
||||
custom_fields = { "action_code_who" => assigned_to.is_a?(User) ? assigned_to.username : assigned_to.name }
|
||||
custom_fields = {
|
||||
"action_code_who" => assigned_to.is_a?(User) ? assigned_to.username : assigned_to.name,
|
||||
}
|
||||
|
||||
if post_target?
|
||||
custom_fields.merge!("action_code_path" => "/p/#{@target.id}")
|
||||
|
@ -345,7 +373,8 @@ class ::Assigner
|
|||
end
|
||||
|
||||
topic.add_moderator_post(
|
||||
@assigned_by, nil,
|
||||
@assigned_by,
|
||||
nil,
|
||||
bump: false,
|
||||
post_type: post_type,
|
||||
custom_fields: custom_fields,
|
||||
|
@ -361,18 +390,16 @@ class ::Assigner
|
|||
topic_id: topic.id,
|
||||
topic_title: topic.title,
|
||||
unassigned_by_id: @assigned_by.id,
|
||||
unassigned_by_username: @assigned_by.username
|
||||
unassigned_by_username: @assigned_by.username,
|
||||
}
|
||||
if assignment.assigned_to_user?
|
||||
payload.merge!({
|
||||
unassigned_to_id: assigned_to.id,
|
||||
unassigned_to_username: assigned_to.username,
|
||||
})
|
||||
payload.merge!(
|
||||
{ unassigned_to_id: assigned_to.id, unassigned_to_username: assigned_to.username },
|
||||
)
|
||||
else
|
||||
payload.merge!({
|
||||
unassigned_to_group_id: assigned_to.id,
|
||||
unassigned_to_group_name: assigned_to.name,
|
||||
})
|
||||
payload.merge!(
|
||||
{ unassigned_to_group_id: assigned_to.id, unassigned_to_group_name: assigned_to.name },
|
||||
)
|
||||
end
|
||||
WebHook.enqueue_assign_hooks(type, payload.to_json)
|
||||
end
|
||||
|
@ -380,14 +407,14 @@ class ::Assigner
|
|||
MessageBus.publish(
|
||||
"/staff/topic-assignment",
|
||||
{
|
||||
type: 'unassigned',
|
||||
type: "unassigned",
|
||||
topic_id: topic.id,
|
||||
post_id: post_target? && @target.id,
|
||||
post_number: post_target? && @target.post_number,
|
||||
assigned_type: assignment.assigned_to.is_a?(User) ? "User" : "Group",
|
||||
assignment_note: nil,
|
||||
},
|
||||
user_ids: allowed_user_ids
|
||||
user_ids: allowed_user_ids,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -395,20 +422,26 @@ class ::Assigner
|
|||
private
|
||||
|
||||
def queue_notification(assign_to, skip_small_action_post)
|
||||
Jobs.enqueue(:assign_notification,
|
||||
Jobs.enqueue(
|
||||
:assign_notification,
|
||||
topic_id: topic.id,
|
||||
post_id: topic_target? ? first_post.id : @target.id,
|
||||
assigned_to_id: assign_to.id,
|
||||
assigned_to_type: assign_to.is_a?(User) ? "User" : "Group",
|
||||
assigned_by_id: @assigned_by.id,
|
||||
skip_small_action_post: skip_small_action_post)
|
||||
skip_small_action_post: skip_small_action_post,
|
||||
)
|
||||
end
|
||||
|
||||
def add_small_action_post(action_code, assign_to, note)
|
||||
custom_fields = { "action_code_who" => assign_to.is_a?(User) ? assign_to.username : assign_to.name }
|
||||
custom_fields = {
|
||||
"action_code_who" => assign_to.is_a?(User) ? assign_to.username : assign_to.name,
|
||||
}
|
||||
|
||||
if post_target?
|
||||
custom_fields.merge!({ "action_code_path" => "/p/#{@target.id}", "action_code_post_id" => @target.id })
|
||||
custom_fields.merge!(
|
||||
{ "action_code_path" => "/p/#{@target.id}", "action_code_post_id" => @target.id },
|
||||
)
|
||||
end
|
||||
|
||||
topic.add_moderator_post(
|
||||
|
@ -417,7 +450,7 @@ class ::Assigner
|
|||
bump: false,
|
||||
post_type: SiteSetting.assigns_public ? Post.types[:small_action] : Post.types[:whisper],
|
||||
action_code: action_code,
|
||||
custom_fields: custom_fields
|
||||
custom_fields: custom_fields,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -434,7 +467,7 @@ class ::Assigner
|
|||
assigned_to: serializer.new(assign_to, scope: Guardian.new, root: false).as_json,
|
||||
assignment_note: note,
|
||||
},
|
||||
user_ids: allowed_user_ids
|
||||
user_ids: allowed_user_ids,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -460,18 +493,18 @@ class ::Assigner
|
|||
|
||||
def topic_same_assignee_and_note(assign_to, type, note)
|
||||
topic.assignment&.assigned_to_id == assign_to.id &&
|
||||
topic.assignment&.assigned_to_type == type &&
|
||||
topic.assignment.active == true &&
|
||||
topic.assignment&.assigned_to_type == type && topic.assignment.active == true &&
|
||||
topic.assignment&.note == note
|
||||
end
|
||||
|
||||
def post_same_assignee_and_note(assign_to, type, note)
|
||||
@target.is_a?(Topic) &&
|
||||
Assignment.where(topic_id: topic.id, target_type: "Post", active: true).any? do |assignment|
|
||||
assignment.assigned_to_id == assign_to.id &&
|
||||
assignment.assigned_to_type == type &&
|
||||
assignment&.note == note
|
||||
end
|
||||
Assignment
|
||||
.where(topic_id: topic.id, target_type: "Post", active: true)
|
||||
.any? do |assignment|
|
||||
assignment.assigned_to_id == assign_to.id && assignment.assigned_to_type == type &&
|
||||
assignment&.note == note
|
||||
end
|
||||
end
|
||||
|
||||
def no_assignee_change?(assignee)
|
||||
|
|
|
@ -8,7 +8,7 @@ module DiscourseAssign
|
|||
username: user.username,
|
||||
name: user.name,
|
||||
avatar_template: user.avatar_template,
|
||||
assign_icon: 'user-plus',
|
||||
assign_icon: "user-plus",
|
||||
assign_path: SiteSetting.assigns_user_url_path.gsub("{username}", user.username),
|
||||
}
|
||||
end
|
||||
|
@ -22,23 +22,39 @@ module DiscourseAssign
|
|||
flair_color: group.flair_color,
|
||||
flair_icon: group.flair_icon,
|
||||
flair_upload_id: group.flair_upload_id,
|
||||
assign_icon: 'group-plus',
|
||||
assign_icon: "group-plus",
|
||||
assign_path: "/g/#{group.name}/assigned/everyone",
|
||||
}
|
||||
end
|
||||
|
||||
def self.build_indirectly_assigned_to(post_assignments, topic)
|
||||
post_assignments.map do |post_id, assigned_map|
|
||||
assigned_to = assigned_map[:assigned_to]
|
||||
note = assigned_map[:assignment_note]
|
||||
post_number = assigned_map[:post_number]
|
||||
post_assignments
|
||||
.map do |post_id, assigned_map|
|
||||
assigned_to = assigned_map[:assigned_to]
|
||||
note = assigned_map[:assignment_note]
|
||||
post_number = assigned_map[:post_number]
|
||||
|
||||
if (assigned_to.is_a?(User))
|
||||
[post_id, { assigned_to: build_assigned_to_user(assigned_to, topic), post_number: post_number, assignment_note: note }]
|
||||
elsif assigned_to.is_a?(Group)
|
||||
[post_id, { assigned_to: build_assigned_to_group(assigned_to, topic), post_number: post_number, assignment_note: note }]
|
||||
if (assigned_to.is_a?(User))
|
||||
[
|
||||
post_id,
|
||||
{
|
||||
assigned_to: build_assigned_to_user(assigned_to, topic),
|
||||
post_number: post_number,
|
||||
assignment_note: note,
|
||||
},
|
||||
]
|
||||
elsif assigned_to.is_a?(Group)
|
||||
[
|
||||
post_id,
|
||||
{
|
||||
assigned_to: build_assigned_to_group(assigned_to, topic),
|
||||
post_number: post_number,
|
||||
assignment_note: note,
|
||||
},
|
||||
]
|
||||
end
|
||||
end
|
||||
end.to_h
|
||||
.to_h
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PendingAssignsReminder
|
||||
REMINDED_AT = 'last_reminded_at'
|
||||
REMINDERS_FREQUENCY = 'remind_assigns_frequency'
|
||||
CUSTOM_FIELD_NAME = 'assigns_reminder'
|
||||
REMINDED_AT = "last_reminded_at"
|
||||
REMINDERS_FREQUENCY = "remind_assigns_frequency"
|
||||
CUSTOM_FIELD_NAME = "assigns_reminder"
|
||||
REMINDER_THRESHOLD = 2
|
||||
|
||||
def remind(user)
|
||||
|
@ -14,7 +14,7 @@ class PendingAssignsReminder
|
|||
|
||||
oldest_topics = assigned_topics(user, order: :asc).where.not(id: newest_topics.map(&:id))
|
||||
assigned_topics_count = assigned_count_for(user)
|
||||
title = I18n.t('pending_assigns_reminder.title', pending_assignments: assigned_topics_count)
|
||||
title = I18n.t("pending_assigns_reminder.title", pending_assignments: assigned_topics_count)
|
||||
|
||||
PostCreator.create!(
|
||||
Discourse.system_user,
|
||||
|
@ -23,7 +23,9 @@ class PendingAssignsReminder
|
|||
archetype: Archetype.private_message,
|
||||
subtype: TopicSubtype.system_message,
|
||||
target_usernames: user.username,
|
||||
custom_fields: { CUSTOM_FIELD_NAME => true }
|
||||
custom_fields: {
|
||||
CUSTOM_FIELD_NAME => true,
|
||||
},
|
||||
)
|
||||
|
||||
update_last_reminded(user)
|
||||
|
@ -32,38 +34,46 @@ class PendingAssignsReminder
|
|||
private
|
||||
|
||||
def delete_previous_reminders(user)
|
||||
posts = Post
|
||||
.joins(topic: { topic_allowed_users: :user })
|
||||
.where(topic: {
|
||||
posts_count: 1,
|
||||
user_id: Discourse.system_user,
|
||||
archetype: Archetype.private_message,
|
||||
subtype: TopicSubtype.system_message,
|
||||
topic_allowed_users: {
|
||||
users: { id: user.id }
|
||||
}
|
||||
})
|
||||
.joins(topic: :_custom_fields)
|
||||
.where(topic_custom_fields: {
|
||||
name: CUSTOM_FIELD_NAME
|
||||
})
|
||||
posts =
|
||||
Post
|
||||
.joins(topic: { topic_allowed_users: :user })
|
||||
.where(
|
||||
topic: {
|
||||
posts_count: 1,
|
||||
user_id: Discourse.system_user,
|
||||
archetype: Archetype.private_message,
|
||||
subtype: TopicSubtype.system_message,
|
||||
topic_allowed_users: {
|
||||
users: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
.joins(topic: :_custom_fields)
|
||||
.where(topic_custom_fields: { name: CUSTOM_FIELD_NAME })
|
||||
|
||||
posts.find_each do |post|
|
||||
PostDestroyer.new(Discourse.system_user, post).destroy
|
||||
end
|
||||
posts.find_each { |post| PostDestroyer.new(Discourse.system_user, post).destroy }
|
||||
end
|
||||
|
||||
def assigned_count_for(user)
|
||||
Assignment.joins_with_topics.where(assigned_to_id: user.id, assigned_to_type: 'User', active: true).count
|
||||
Assignment
|
||||
.joins_with_topics
|
||||
.where(assigned_to_id: user.id, assigned_to_type: "User", active: true)
|
||||
.count
|
||||
end
|
||||
|
||||
def assigned_topics(user, order:)
|
||||
secure = Topic.listable_topics.secured(Guardian.new(user)).or(Topic.private_messages_for_user(user))
|
||||
secure =
|
||||
Topic.listable_topics.secured(Guardian.new(user)).or(Topic.private_messages_for_user(user))
|
||||
|
||||
Topic
|
||||
.joins(:assignment)
|
||||
.select(:slug, :id, :title, :fancy_title, 'assignments.created_at AS assigned_at')
|
||||
.where("assignments.assigned_to_id = ? AND assignments.assigned_to_type = 'User' AND assignments.active", user.id)
|
||||
.select(:slug, :id, :title, :fancy_title, "assignments.created_at AS assigned_at")
|
||||
.where(
|
||||
"assignments.assigned_to_id = ? AND assignments.assigned_to_type = 'User' AND assignments.active",
|
||||
user.id,
|
||||
)
|
||||
.merge(secure)
|
||||
.order("assignments.created_at #{order}")
|
||||
.limit(3)
|
||||
|
@ -74,38 +84,47 @@ class PendingAssignsReminder
|
|||
oldest_list = build_list_for(:oldest, last_three_topics)
|
||||
|
||||
I18n.t(
|
||||
'pending_assigns_reminder.body',
|
||||
"pending_assigns_reminder.body",
|
||||
pending_assignments: assigned_topics_count,
|
||||
assignments_link: "#{Discourse.base_url}/u/#{user.username_lower}/activity/assigned",
|
||||
newest_assignments: newest_list,
|
||||
oldest_assignments: oldest_list,
|
||||
frequency: frequency_in_words(user)
|
||||
frequency: frequency_in_words(user),
|
||||
)
|
||||
end
|
||||
|
||||
def build_list_for(key, topics)
|
||||
return '' if topics.empty?
|
||||
initial_list = { 'topic_0' => '', 'topic_1' => '', 'topic_2' => '' }
|
||||
items = topics.each_with_index.reduce(initial_list) do |memo, (t, index)|
|
||||
memo["topic_#{index}"] = "- [#{Emoji.gsub_emoji_to_unicode(t.fancy_title)}](#{t.relative_url}) - assigned #{time_in_words_for(t)}"
|
||||
memo
|
||||
end
|
||||
return "" if topics.empty?
|
||||
initial_list = { "topic_0" => "", "topic_1" => "", "topic_2" => "" }
|
||||
items =
|
||||
topics
|
||||
.each_with_index
|
||||
.reduce(initial_list) do |memo, (t, index)|
|
||||
memo[
|
||||
"topic_#{index}"
|
||||
] = "- [#{Emoji.gsub_emoji_to_unicode(t.fancy_title)}](#{t.relative_url}) - assigned #{time_in_words_for(t)}"
|
||||
memo
|
||||
end
|
||||
|
||||
I18n.t("pending_assigns_reminder.#{key}", items.symbolize_keys!)
|
||||
end
|
||||
|
||||
def time_in_words_for(topic)
|
||||
FreedomPatches::Rails4.distance_of_time_in_words(
|
||||
Time.zone.now, topic.assigned_at.to_time, false, scope: 'datetime.distance_in_words_verbose'
|
||||
Time.zone.now,
|
||||
topic.assigned_at.to_time,
|
||||
false,
|
||||
scope: "datetime.distance_in_words_verbose",
|
||||
)
|
||||
end
|
||||
|
||||
def frequency_in_words(user)
|
||||
frequency = if user.custom_fields&.has_key?(REMINDERS_FREQUENCY)
|
||||
user.custom_fields[REMINDERS_FREQUENCY]
|
||||
else
|
||||
SiteSetting.remind_assigns_frequency
|
||||
end
|
||||
frequency =
|
||||
if user.custom_fields&.has_key?(REMINDERS_FREQUENCY)
|
||||
user.custom_fields[REMINDERS_FREQUENCY]
|
||||
else
|
||||
SiteSetting.remind_assigns_frequency
|
||||
end
|
||||
|
||||
::RemindAssignsFrequencySiteSettings.frequency_for(frequency)
|
||||
end
|
||||
|
|
|
@ -10,11 +10,9 @@ class RandomAssignUtils
|
|||
end
|
||||
|
||||
def self.automation_script!(context, fields, automation)
|
||||
unless SiteSetting.assign_enabled?
|
||||
raise_error(automation, "discourse-assign is not enabled")
|
||||
end
|
||||
raise_error(automation, "discourse-assign is not enabled") unless SiteSetting.assign_enabled?
|
||||
|
||||
unless topic_id = fields.dig('assigned_topic', 'value')
|
||||
unless topic_id = fields.dig("assigned_topic", "value")
|
||||
raise_error(automation, "`assigned_topic` not provided")
|
||||
end
|
||||
|
||||
|
@ -22,16 +20,17 @@ class RandomAssignUtils
|
|||
raise_error(automation, "Topic(#{topic_id}) not found")
|
||||
end
|
||||
|
||||
min_hours = fields.dig('minimum_time_between_assignments', 'value').presence
|
||||
if min_hours && TopicCustomField
|
||||
.where(name: 'assigned_to_id', topic_id: topic_id)
|
||||
.where('created_at < ?', min_hours.to_i.hours.ago)
|
||||
.exists?
|
||||
min_hours = fields.dig("minimum_time_between_assignments", "value").presence
|
||||
if min_hours &&
|
||||
TopicCustomField
|
||||
.where(name: "assigned_to_id", topic_id: topic_id)
|
||||
.where("created_at < ?", min_hours.to_i.hours.ago)
|
||||
.exists?
|
||||
log_info(automation, "Topic(#{topic_id}) has already been assigned recently")
|
||||
return
|
||||
end
|
||||
|
||||
unless group_id = fields.dig('assignees_group', 'value')
|
||||
unless group_id = fields.dig("assignees_group", "value")
|
||||
raise_error(automation, "`assignees_group` not provided")
|
||||
end
|
||||
|
||||
|
@ -39,32 +38,35 @@ class RandomAssignUtils
|
|||
raise_error(automation, "Group(#{group_id}) not found")
|
||||
end
|
||||
|
||||
users_on_holiday = Set.new(
|
||||
User
|
||||
.where(id:
|
||||
UserCustomField
|
||||
.where(name: 'on_holiday', value: 't')
|
||||
.select(:user_id)
|
||||
).pluck(:id)
|
||||
)
|
||||
users_on_holiday =
|
||||
Set.new(
|
||||
User.where(
|
||||
id: UserCustomField.where(name: "on_holiday", value: "t").select(:user_id),
|
||||
).pluck(:id),
|
||||
)
|
||||
|
||||
group_users_ids = group
|
||||
.group_users
|
||||
.joins(:user)
|
||||
.pluck('users.id')
|
||||
.reject { |user_id| users_on_holiday.include?(user_id) }
|
||||
group_users_ids =
|
||||
group
|
||||
.group_users
|
||||
.joins(:user)
|
||||
.pluck("users.id")
|
||||
.reject { |user_id| users_on_holiday.include?(user_id) }
|
||||
|
||||
if group_users_ids.empty?
|
||||
RandomAssignUtils.no_one!(topic_id, group.name)
|
||||
return
|
||||
end
|
||||
|
||||
max_recently_assigned_days = (fields.dig('max_recently_assigned_days', 'value').presence || 180).to_i.days.ago
|
||||
last_assignees_ids = RandomAssignUtils.recently_assigned_users_ids(topic_id, max_recently_assigned_days)
|
||||
max_recently_assigned_days =
|
||||
(fields.dig("max_recently_assigned_days", "value").presence || 180).to_i.days.ago
|
||||
last_assignees_ids =
|
||||
RandomAssignUtils.recently_assigned_users_ids(topic_id, max_recently_assigned_days)
|
||||
users_ids = group_users_ids - last_assignees_ids
|
||||
if users_ids.blank?
|
||||
min_recently_assigned_days = (fields.dig('min_recently_assigned_days', 'value').presence || 14).to_i.days.ago
|
||||
recently_assigned_users_ids = RandomAssignUtils.recently_assigned_users_ids(topic_id, min_recently_assigned_days)
|
||||
min_recently_assigned_days =
|
||||
(fields.dig("min_recently_assigned_days", "value").presence || 14).to_i.days.ago
|
||||
recently_assigned_users_ids =
|
||||
RandomAssignUtils.recently_assigned_users_ids(topic_id, min_recently_assigned_days)
|
||||
users_ids = group_users_ids - recently_assigned_users_ids
|
||||
end
|
||||
|
||||
|
@ -73,10 +75,9 @@ class RandomAssignUtils
|
|||
return
|
||||
end
|
||||
|
||||
if fields.dig('in_working_hours', 'value')
|
||||
assign_to_user_id = users_ids.shuffle.find do |user_id|
|
||||
RandomAssignUtils.in_working_hours?(user_id)
|
||||
end
|
||||
if fields.dig("in_working_hours", "value")
|
||||
assign_to_user_id =
|
||||
users_ids.shuffle.find { |user_id| RandomAssignUtils.in_working_hours?(user_id) }
|
||||
end
|
||||
|
||||
assign_to_user_id ||= users_ids.sample
|
||||
|
@ -87,35 +88,34 @@ class RandomAssignUtils
|
|||
|
||||
assign_to = User.find(assign_to_user_id)
|
||||
result = nil
|
||||
if raw = fields.dig('post_template', 'value').presence
|
||||
post = PostCreator.new(
|
||||
Discourse.system_user,
|
||||
raw: raw,
|
||||
skip_validations: true,
|
||||
topic_id: topic.id
|
||||
).create!
|
||||
if raw = fields.dig("post_template", "value").presence
|
||||
post =
|
||||
PostCreator.new(
|
||||
Discourse.system_user,
|
||||
raw: raw,
|
||||
skip_validations: true,
|
||||
topic_id: topic.id,
|
||||
).create!
|
||||
|
||||
result = Assigner.new(post, Discourse.system_user).assign(assign_to)
|
||||
|
||||
if !result[:success]
|
||||
PostDestroyer.new(Discourse.system_user, post).destroy
|
||||
end
|
||||
PostDestroyer.new(Discourse.system_user, post).destroy if !result[:success]
|
||||
else
|
||||
result = Assigner.new(topic, Discourse.system_user).assign(assign_to)
|
||||
end
|
||||
|
||||
if !result[:success]
|
||||
RandomAssignUtils.no_one!(topic_id, group.name)
|
||||
end
|
||||
RandomAssignUtils.no_one!(topic_id, group.name) if !result[:success]
|
||||
end
|
||||
|
||||
def self.recently_assigned_users_ids(topic_id, from)
|
||||
posts = Post
|
||||
.joins(:user)
|
||||
.where(topic_id: topic_id, action_code: ['assigned', 'reassigned', 'assigned_to_post'])
|
||||
.where('posts.created_at > ?', from)
|
||||
.order(created_at: :desc)
|
||||
usernames = Post.custom_fields_for_ids(posts, [:action_code_who]).map { |_, v| v['action_code_who'] }.uniq
|
||||
posts =
|
||||
Post
|
||||
.joins(:user)
|
||||
.where(topic_id: topic_id, action_code: %w[assigned reassigned assigned_to_post])
|
||||
.where("posts.created_at > ?", from)
|
||||
.order(created_at: :desc)
|
||||
usernames =
|
||||
Post.custom_fields_for_ids(posts, [:action_code_who]).map { |_, v| v["action_code_who"] }.uniq
|
||||
User.where(username: usernames).limit(100).pluck(:id)
|
||||
end
|
||||
|
||||
|
@ -126,7 +126,9 @@ class RandomAssignUtils
|
|||
begin
|
||||
tzinfo = ActiveSupport::TimeZone.find_tzinfo(timezone)
|
||||
rescue TZInfo::InvalidTimezoneIdentifier
|
||||
Rails.logger.warn("#{User.find_by(id: user_id)&.username} has the timezone #{timezone} set, we do not know how to parse it in Rails (assuming UTC)")
|
||||
Rails.logger.warn(
|
||||
"#{User.find_by(id: user_id)&.username} has the timezone #{timezone} set, we do not know how to parse it in Rails (assuming UTC)",
|
||||
)
|
||||
timezone = "UTC"
|
||||
tzinfo = ActiveSupport::TimeZone.find_tzinfo(timezone)
|
||||
end
|
||||
|
@ -139,7 +141,7 @@ class RandomAssignUtils
|
|||
Discourse.system_user,
|
||||
topic_id: topic_id,
|
||||
raw: I18n.t("discourse_automation.scriptables.random_assign.no_one", group: group),
|
||||
validate: false
|
||||
validate: false,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -147,9 +149,6 @@ class RandomAssignUtils
|
|||
tzinfo = RandomAssignUtils.user_tzinfo(user_id)
|
||||
tztime = tzinfo.now
|
||||
|
||||
!tztime.saturday? &&
|
||||
!tztime.sunday? &&
|
||||
tztime.hour > 7 &&
|
||||
tztime.hour < 11
|
||||
!tztime.saturday? && !tztime.sunday? && tztime.hour > 7 && tztime.hour < 11
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,10 @@ class ::TopicAssigner
|
|||
end
|
||||
|
||||
def self.deprecation_note
|
||||
Discourse.deprecate("TopicAssigner class is deprecated, use Assigner", since: "2.8", drop_from: "2.9")
|
||||
Discourse.deprecate(
|
||||
"TopicAssigner class is deprecated, use Assigner",
|
||||
since: "2.8",
|
||||
drop_from: "2.9",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
474
plugin.rb
474
plugin.rb
|
@ -9,34 +9,46 @@
|
|||
|
||||
enabled_site_setting :assign_enabled
|
||||
|
||||
register_asset 'stylesheets/assigns.scss'
|
||||
register_asset 'stylesheets/mobile/assigns.scss', :mobile
|
||||
register_asset "stylesheets/assigns.scss"
|
||||
register_asset "stylesheets/mobile/assigns.scss", :mobile
|
||||
|
||||
register_svg_icon "user-plus"
|
||||
register_svg_icon "user-times"
|
||||
|
||||
%w[user-plus user-times group-plus group-times].each { |i| register_svg_icon(i) }
|
||||
|
||||
load File.expand_path('../lib/discourse_assign/engine.rb', __FILE__)
|
||||
load File.expand_path('../lib/discourse_assign/helpers.rb', __FILE__)
|
||||
load File.expand_path("../lib/discourse_assign/engine.rb", __FILE__)
|
||||
load File.expand_path("../lib/discourse_assign/helpers.rb", __FILE__)
|
||||
|
||||
Discourse::Application.routes.append do
|
||||
mount ::DiscourseAssign::Engine, at: "/assign"
|
||||
get "topics/private-messages-assigned/:username" => "list#private_messages_assigned", as: "topics_private_messages_assigned", constraints: { username: ::RouteFormat.username }
|
||||
get "/topics/messages-assigned/:username" => "list#messages_assigned", constraints: { username: ::RouteFormat.username }, as: "messages_assigned"
|
||||
get "/topics/group-topics-assigned/:groupname" => "list#group_topics_assigned", constraints: { username: ::RouteFormat.username }, as: "group_topics_assigned"
|
||||
get "topics/private-messages-assigned/:username" => "list#private_messages_assigned",
|
||||
:as => "topics_private_messages_assigned",
|
||||
:constraints => {
|
||||
username: ::RouteFormat.username,
|
||||
}
|
||||
get "/topics/messages-assigned/:username" => "list#messages_assigned",
|
||||
:constraints => {
|
||||
username: ::RouteFormat.username,
|
||||
},
|
||||
:as => "messages_assigned"
|
||||
get "/topics/group-topics-assigned/:groupname" => "list#group_topics_assigned",
|
||||
:constraints => {
|
||||
username: ::RouteFormat.username,
|
||||
},
|
||||
:as => "group_topics_assigned"
|
||||
get "/g/:id/assigned" => "groups#index"
|
||||
get "/g/:id/assigned/:route_type" => "groups#index"
|
||||
end
|
||||
|
||||
after_initialize do
|
||||
require File.expand_path('../jobs/scheduled/enqueue_reminders.rb', __FILE__)
|
||||
require File.expand_path('../jobs/regular/remind_user.rb', __FILE__)
|
||||
require File.expand_path('../jobs/regular/assign_notification.rb', __FILE__)
|
||||
require File.expand_path('../jobs/regular/unassign_notification.rb', __FILE__)
|
||||
require 'topic_assigner'
|
||||
require 'assigner'
|
||||
require 'pending_assigns_reminder'
|
||||
require File.expand_path("../jobs/scheduled/enqueue_reminders.rb", __FILE__)
|
||||
require File.expand_path("../jobs/regular/remind_user.rb", __FILE__)
|
||||
require File.expand_path("../jobs/regular/assign_notification.rb", __FILE__)
|
||||
require File.expand_path("../jobs/regular/unassign_notification.rb", __FILE__)
|
||||
require "topic_assigner"
|
||||
require "assigner"
|
||||
require "pending_assigns_reminder"
|
||||
|
||||
register_group_param(:assignable_level)
|
||||
register_groups_callback_for_users_search_controller_action(:assignable_groups) do |groups, user|
|
||||
|
@ -53,16 +65,21 @@ after_initialize do
|
|||
end
|
||||
|
||||
class ::Group
|
||||
scope :assignable, ->(user) {
|
||||
where("assignable_level in (:levels) OR
|
||||
scope :assignable,
|
||||
->(user) {
|
||||
where(
|
||||
"assignable_level in (:levels) OR
|
||||
(
|
||||
assignable_level = #{ALIAS_LEVELS[:members_mods_and_admins]} AND id in (
|
||||
SELECT group_id FROM group_users WHERE user_id = :user_id)
|
||||
) OR (
|
||||
assignable_level = #{ALIAS_LEVELS[:owners_mods_and_admins]} AND id in (
|
||||
SELECT group_id FROM group_users WHERE user_id = :user_id AND owner IS TRUE)
|
||||
)", levels: alias_levels(user), user_id: user && user.id)
|
||||
}
|
||||
)",
|
||||
levels: alias_levels(user),
|
||||
user_id: user && user.id,
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -70,17 +87,13 @@ after_initialize do
|
|||
register_editable_user_custom_field frequency_field
|
||||
User.register_custom_field_type frequency_field, :integer
|
||||
DiscoursePluginRegistry.serialized_current_user_fields << frequency_field
|
||||
add_to_serializer(:user, :reminders_frequency) do
|
||||
RemindAssignsFrequencySiteSettings.values
|
||||
end
|
||||
add_to_serializer(:user, :reminders_frequency) { RemindAssignsFrequencySiteSettings.values }
|
||||
|
||||
add_to_serializer(:group_show, :assignment_count) do
|
||||
Topic
|
||||
.joins(<<~SQL)
|
||||
Topic.joins(<<~SQL).where(<<~SQL, group_id: object.id).where("topics.deleted_at IS NULL").count
|
||||
JOIN assignments a
|
||||
ON topics.id = a.topic_id AND a.assigned_to_id IS NOT NULL
|
||||
SQL
|
||||
.where(<<~SQL, group_id: object.id)
|
||||
a.active AND
|
||||
((
|
||||
a.assigned_to_type = 'User' AND a.assigned_to_id IN (
|
||||
|
@ -92,28 +105,20 @@ after_initialize do
|
|||
a.assigned_to_type = 'Group' AND a.assigned_to_id = :group_id
|
||||
))
|
||||
SQL
|
||||
.where("topics.deleted_at IS NULL")
|
||||
.count
|
||||
end
|
||||
|
||||
add_to_serializer(:group_show, 'include_assignment_count?') do
|
||||
scope.can_assign?
|
||||
end
|
||||
add_to_serializer(:group_show, "include_assignment_count?") { scope.can_assign? }
|
||||
|
||||
add_to_serializer(:group_show, :assignable_level) do
|
||||
object.assignable_level
|
||||
end
|
||||
add_to_serializer(:group_show, :assignable_level) { object.assignable_level }
|
||||
|
||||
add_to_serializer(:group_show, :can_show_assigned_tab?) do
|
||||
object.can_show_assigned_tab?
|
||||
end
|
||||
add_to_serializer(:group_show, :can_show_assigned_tab?) { object.can_show_assigned_tab? }
|
||||
|
||||
add_model_callback(UserCustomField, :before_save) do
|
||||
self.value = self.value.to_i if self.name == frequency_field
|
||||
end
|
||||
|
||||
add_class_method(:group, :assign_allowed_groups) do
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split('|')
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split("|")
|
||||
where(id: allowed_groups)
|
||||
end
|
||||
|
||||
|
@ -121,21 +126,24 @@ after_initialize do
|
|||
@can_assign ||=
|
||||
begin
|
||||
return true if admin?
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split('|').compact
|
||||
allowed_groups.present? && groups.where(id: allowed_groups).exists? ?
|
||||
:true : :false
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split("|").compact
|
||||
allowed_groups.present? && groups.where(id: allowed_groups).exists? ? :true : :false
|
||||
end
|
||||
@can_assign == :true
|
||||
end
|
||||
|
||||
add_to_serializer(:current_user, :never_auto_track_topics) do
|
||||
(user.user_option.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs) < 0
|
||||
(
|
||||
user.user_option.auto_track_topics_after_msecs ||
|
||||
SiteSetting.default_other_auto_track_topics_after_msecs
|
||||
) < 0
|
||||
end
|
||||
|
||||
add_to_class(:group, :can_show_assigned_tab?) do
|
||||
allowed_group_ids = SiteSetting.assign_allowed_on_groups.split("|")
|
||||
|
||||
group_has_disallowed_users = DB.query_single(<<~SQL, allowed_group_ids: allowed_group_ids, current_group_id: self.id)[0]
|
||||
group_has_disallowed_users =
|
||||
DB.query_single(<<~SQL, allowed_group_ids: allowed_group_ids, current_group_id: self.id)[0]
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM users
|
||||
JOIN group_users current_group_users
|
||||
|
@ -154,11 +162,12 @@ after_initialize do
|
|||
add_to_class(:guardian, :can_assign?) { user && user.can_assign? }
|
||||
|
||||
add_class_method(:user, :assign_allowed) do
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split('|')
|
||||
allowed_groups = SiteSetting.assign_allowed_on_groups.split("|")
|
||||
|
||||
# The UNION against admin users is necessary because bot users like the system user are given the admin status but
|
||||
# are not added into the admin group.
|
||||
where("users.id IN (
|
||||
where(
|
||||
"users.id IN (
|
||||
SELECT
|
||||
user_id
|
||||
FROM group_users
|
||||
|
@ -169,39 +178,46 @@ after_initialize do
|
|||
SELECT id
|
||||
FROM users
|
||||
WHERE users.admin
|
||||
)", allowed_groups)
|
||||
)",
|
||||
allowed_groups,
|
||||
)
|
||||
end
|
||||
|
||||
add_model_callback(Group, :before_update) do
|
||||
if name_changed?
|
||||
SiteSetting.assign_allowed_on_groups = SiteSetting.assign_allowed_on_groups.gsub(name_was, name)
|
||||
SiteSetting.assign_allowed_on_groups =
|
||||
SiteSetting.assign_allowed_on_groups.gsub(name_was, name)
|
||||
end
|
||||
end
|
||||
|
||||
add_model_callback(Group, :before_destroy) do
|
||||
new_setting = SiteSetting.assign_allowed_on_groups.gsub(/#{id}[|]?/, '')
|
||||
new_setting = new_setting.chomp('|') if new_setting.ends_with?('|')
|
||||
new_setting = SiteSetting.assign_allowed_on_groups.gsub(/#{id}[|]?/, "")
|
||||
new_setting = new_setting.chomp("|") if new_setting.ends_with?("|")
|
||||
SiteSetting.assign_allowed_on_groups = new_setting
|
||||
end
|
||||
|
||||
on(:assign_topic) do |topic, user, assigning_user, force|
|
||||
if force || !Assignment.exists?(target: topic)
|
||||
Assigner.new(topic, assigning_user).assign(user)
|
||||
end
|
||||
Assigner.new(topic, assigning_user).assign(user) if force || !Assignment.exists?(target: topic)
|
||||
end
|
||||
|
||||
on(:unassign_topic) do |topic, unassigning_user|
|
||||
Assigner.new(topic, unassigning_user).unassign
|
||||
end
|
||||
on(:unassign_topic) { |topic, unassigning_user| Assigner.new(topic, unassigning_user).unassign }
|
||||
|
||||
Site.preloaded_category_custom_fields << "enable_unassigned_filter"
|
||||
|
||||
BookmarkQuery.on_preload do |bookmarks, bookmark_query|
|
||||
if SiteSetting.assign_enabled?
|
||||
topics = Bookmark.select_type(bookmarks, "Topic").map(&:bookmarkable).concat(
|
||||
Bookmark.select_type(bookmarks, "Post").map { |bm| bm.bookmarkable.topic }
|
||||
).uniq
|
||||
assignments = Assignment.strict_loading.where(topic_id: topics).includes(:assigned_to).index_by(&:topic_id)
|
||||
topics =
|
||||
Bookmark
|
||||
.select_type(bookmarks, "Topic")
|
||||
.map(&:bookmarkable)
|
||||
.concat(Bookmark.select_type(bookmarks, "Post").map { |bm| bm.bookmarkable.topic })
|
||||
.uniq
|
||||
assignments =
|
||||
Assignment
|
||||
.strict_loading
|
||||
.where(topic_id: topics)
|
||||
.includes(:assigned_to)
|
||||
.index_by(&:topic_id)
|
||||
|
||||
topics.each do |topic|
|
||||
assigned_to = assignments[topic.id]&.assigned_to
|
||||
|
@ -223,22 +239,40 @@ after_initialize do
|
|||
assignments = Assignment.strict_loading.where(topic: topics, active: true).includes(:target)
|
||||
assignments_map = assignments.group_by(&:topic_id)
|
||||
|
||||
user_ids = assignments.filter { |assignment| assignment.assigned_to_user? }.map(&:assigned_to_id)
|
||||
user_ids =
|
||||
assignments.filter { |assignment| assignment.assigned_to_user? }.map(&:assigned_to_id)
|
||||
users_map = User.where(id: user_ids).select(UserLookup.lookup_columns).index_by(&:id)
|
||||
|
||||
group_ids = assignments.filter { |assignment| assignment.assigned_to_group? }.map(&:assigned_to_id)
|
||||
group_ids =
|
||||
assignments.filter { |assignment| assignment.assigned_to_group? }.map(&:assigned_to_id)
|
||||
groups_map = Group.where(id: group_ids).index_by(&:id)
|
||||
|
||||
topics.each do |topic|
|
||||
assignments = assignments_map[topic.id]
|
||||
direct_assignment = assignments&.find { |assignment| assignment.target_type == "Topic" && assignment.target_id == topic.id }
|
||||
direct_assignment =
|
||||
assignments&.find do |assignment|
|
||||
assignment.target_type == "Topic" && assignment.target_id == topic.id
|
||||
end
|
||||
indirectly_assigned_to = {}
|
||||
assignments&.each do |assignment|
|
||||
next if assignment.target_type == "Topic"
|
||||
next if !assignment.target
|
||||
next indirectly_assigned_to[assignment.target_id] = { assigned_to: users_map[assignment.assigned_to_id], post_number: assignment.target.post_number } if assignment&.assigned_to_user?
|
||||
next indirectly_assigned_to[assignment.target_id] = { assigned_to: groups_map[assignment.assigned_to_id], post_number: assignment.target.post_number } if assignment&.assigned_to_group?
|
||||
end&.compact&.uniq
|
||||
assignments
|
||||
&.each do |assignment|
|
||||
next if assignment.target_type == "Topic"
|
||||
next if !assignment.target
|
||||
next(
|
||||
indirectly_assigned_to[assignment.target_id] = {
|
||||
assigned_to: users_map[assignment.assigned_to_id],
|
||||
post_number: assignment.target.post_number,
|
||||
}
|
||||
) if assignment&.assigned_to_user?
|
||||
next(
|
||||
indirectly_assigned_to[assignment.target_id] = {
|
||||
assigned_to: groups_map[assignment.assigned_to_id],
|
||||
post_number: assignment.target.post_number,
|
||||
}
|
||||
) if assignment&.assigned_to_group?
|
||||
end
|
||||
&.compact
|
||||
&.uniq
|
||||
|
||||
assigned_to =
|
||||
if direct_assignment&.assigned_to_user?
|
||||
|
@ -260,23 +294,34 @@ after_initialize do
|
|||
|
||||
if allowed_access && results.posts.length > 0
|
||||
topics = results.posts.map(&:topic)
|
||||
assignments = Assignment.strict_loading.where(topic: topics, active: true).includes(:assigned_to, :target).group_by(&:topic_id)
|
||||
assignments =
|
||||
Assignment
|
||||
.strict_loading
|
||||
.where(topic: topics, active: true)
|
||||
.includes(:assigned_to, :target)
|
||||
.group_by(&:topic_id)
|
||||
|
||||
results.posts.each do |post|
|
||||
topic_assignments = assignments[post.topic.id]
|
||||
direct_assignment = topic_assignments&.find { |assignment| assignment.target_type == "Topic" }
|
||||
indirect_assignments = topic_assignments&.select { |assignment| assignment.target_type == "Post" }
|
||||
direct_assignment =
|
||||
topic_assignments&.find { |assignment| assignment.target_type == "Topic" }
|
||||
indirect_assignments =
|
||||
topic_assignments&.select { |assignment| assignment.target_type == "Post" }
|
||||
if direct_assignment
|
||||
assigned_to = direct_assignment.assigned_to
|
||||
post.topic.preload_assigned_to(assigned_to)
|
||||
end
|
||||
if indirect_assignments.present?
|
||||
indirect_assignment_map = indirect_assignments.reduce({}) do |acc, assignment|
|
||||
if assignment.target
|
||||
acc[assignment.target_id] = { assigned_to: assignment.assigned_to, post_number: assignment.target.post_number }
|
||||
indirect_assignment_map =
|
||||
indirect_assignments.reduce({}) do |acc, assignment|
|
||||
if assignment.target
|
||||
acc[assignment.target_id] = {
|
||||
assigned_to: assignment.assigned_to,
|
||||
post_number: assignment.target.post_number,
|
||||
}
|
||||
end
|
||||
acc
|
||||
end
|
||||
acc
|
||||
end
|
||||
post.topic.preload_indirectly_assigned_to(indirect_assignment_map)
|
||||
end
|
||||
end
|
||||
|
@ -285,7 +330,7 @@ after_initialize do
|
|||
end
|
||||
|
||||
# TopicQuery
|
||||
require_dependency 'topic_query'
|
||||
require_dependency "topic_query"
|
||||
TopicQuery.add_custom_filter(:assigned) do |results, topic_query|
|
||||
name = topic_query.options[:assigned]
|
||||
next results if name.blank?
|
||||
|
@ -293,32 +338,42 @@ after_initialize do
|
|||
next results if !topic_query.guardian.can_assign? && !SiteSetting.assigns_public
|
||||
|
||||
if name == "nobody"
|
||||
next results
|
||||
.joins("LEFT JOIN assignments a ON a.topic_id = topics.id AND active")
|
||||
.where("a.assigned_to_id IS NULL")
|
||||
next(
|
||||
results.joins("LEFT JOIN assignments a ON a.topic_id = topics.id AND active").where(
|
||||
"a.assigned_to_id IS NULL",
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
if name == "*"
|
||||
next results
|
||||
.joins("JOIN assignments a ON a.topic_id = topics.id AND active")
|
||||
.where("a.assigned_to_id IS NOT NULL")
|
||||
next(
|
||||
results.joins("JOIN assignments a ON a.topic_id = topics.id AND active").where(
|
||||
"a.assigned_to_id IS NOT NULL",
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
user_id = topic_query.guardian.user.id if name == "me"
|
||||
user_id ||= User.where(username_lower: name.downcase).pluck_first(:id)
|
||||
|
||||
if user_id
|
||||
next results
|
||||
.joins("JOIN assignments a ON a.topic_id = topics.id AND active")
|
||||
.where("a.assigned_to_id = ? AND a.assigned_to_type = 'User'", user_id)
|
||||
next(
|
||||
results.joins("JOIN assignments a ON a.topic_id = topics.id AND active").where(
|
||||
"a.assigned_to_id = ? AND a.assigned_to_type = 'User'",
|
||||
user_id,
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
group_id = Group.where(name: name.downcase).pluck_first(:id)
|
||||
|
||||
if group_id
|
||||
next results
|
||||
.joins("JOIN assignments a ON a.topic_id = topics.id AND active")
|
||||
.where("a.assigned_to_id = ? AND a.assigned_to_type = 'Group'", group_id)
|
||||
next(
|
||||
results.joins("JOIN assignments a ON a.topic_id = topics.id AND active").where(
|
||||
"a.assigned_to_id = ? AND a.assigned_to_type = 'Group'",
|
||||
group_id,
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
next results
|
||||
|
@ -334,11 +389,9 @@ after_initialize do
|
|||
(assigned_to_id = :user_id AND assigned_to_type = 'User' AND active)
|
||||
SQL
|
||||
|
||||
if @options[:filter] != :direct
|
||||
topic_ids_sql << <<~SQL
|
||||
topic_ids_sql << <<~SQL if @options[:filter] != :direct
|
||||
OR (assigned_to_id IN (group_users.group_id) AND assigned_to_type = 'Group' AND active)
|
||||
SQL
|
||||
end
|
||||
|
||||
sql = "topics.id IN (#{topic_ids_sql})"
|
||||
|
||||
|
@ -357,13 +410,11 @@ after_initialize do
|
|||
)
|
||||
SQL
|
||||
|
||||
if @options[:filter] != :direct
|
||||
topic_ids_sql << <<~SQL
|
||||
topic_ids_sql << <<~SQL if @options[:filter] != :direct
|
||||
OR (
|
||||
assigned_to_id IN (SELECT user_id from group_users where group_id = :group_id) AND assigned_to_type = 'User' AND active
|
||||
)
|
||||
SQL
|
||||
end
|
||||
|
||||
sql = "topics.id IN (#{topic_ids_sql})"
|
||||
|
||||
|
@ -395,7 +446,7 @@ after_initialize do
|
|||
end
|
||||
|
||||
# ListController
|
||||
require_dependency 'list_controller'
|
||||
require_dependency "list_controller"
|
||||
class ::ListController
|
||||
generate_message_route(:private_messages_assigned)
|
||||
end
|
||||
|
@ -441,15 +492,21 @@ after_initialize do
|
|||
|
||||
add_to_class(:topic, :indirectly_assigned_to) do
|
||||
return @indirectly_assigned_to if defined?(@indirectly_assigned_to)
|
||||
@indirectly_assigned_to = Assignment.where(topic_id: id, target_type: "Post", active: true).includes(:target).inject({}) do |acc, assignment|
|
||||
acc[assignment.target_id] = { assigned_to: assignment.assigned_to, post_number: assignment.target.post_number, assignment_note: assignment.note } if assignment.target
|
||||
acc
|
||||
end
|
||||
@indirectly_assigned_to =
|
||||
Assignment
|
||||
.where(topic_id: id, target_type: "Post", active: true)
|
||||
.includes(:target)
|
||||
.inject({}) do |acc, assignment|
|
||||
acc[assignment.target_id] = {
|
||||
assigned_to: assignment.assigned_to,
|
||||
post_number: assignment.target.post_number,
|
||||
assignment_note: assignment.note,
|
||||
} if assignment.target
|
||||
acc
|
||||
end
|
||||
end
|
||||
|
||||
add_to_class(:topic, :preload_assigned_to) do |assigned_to|
|
||||
@assigned_to = assigned_to
|
||||
end
|
||||
add_to_class(:topic, :preload_assigned_to) { |assigned_to| @assigned_to = assigned_to }
|
||||
|
||||
add_to_class(:topic, :preload_indirectly_assigned_to) do |indirectly_assigned_to|
|
||||
@indirectly_assigned_to = indirectly_assigned_to
|
||||
|
@ -457,17 +514,17 @@ after_initialize do
|
|||
|
||||
# TopicList serializer
|
||||
add_to_serializer(:topic_list, :assigned_messages_count) do
|
||||
TopicQuery.new(object.current_user, guardian: scope, limit: false)
|
||||
TopicQuery
|
||||
.new(object.current_user, guardian: scope, limit: false)
|
||||
.private_messages_assigned_query(object.current_user)
|
||||
.count
|
||||
end
|
||||
|
||||
add_to_serializer(:topic_list, 'include_assigned_messages_count?') do
|
||||
add_to_serializer(:topic_list, "include_assigned_messages_count?") do
|
||||
options = object.instance_variable_get(:@opts)
|
||||
|
||||
if assigned_user = options.dig(:assigned)
|
||||
scope.can_assign? ||
|
||||
assigned_user.downcase == scope.current_user&.username_lower
|
||||
scope.can_assign? || assigned_user.downcase == scope.current_user&.username_lower
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -489,16 +546,18 @@ after_initialize do
|
|||
end
|
||||
|
||||
add_to_serializer(:topic_view, :indirectly_assigned_to) do
|
||||
DiscourseAssign::Helpers.build_indirectly_assigned_to(object.topic.indirectly_assigned_to, object.topic)
|
||||
DiscourseAssign::Helpers.build_indirectly_assigned_to(
|
||||
object.topic.indirectly_assigned_to,
|
||||
object.topic,
|
||||
)
|
||||
end
|
||||
|
||||
add_to_serializer(:topic_view, :include_indirectly_assigned_to?) do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.topic.indirectly_assigned_to.present?
|
||||
(SiteSetting.assigns_public || scope.can_assign?) &&
|
||||
object.topic.indirectly_assigned_to.present?
|
||||
end
|
||||
|
||||
add_to_serializer(:topic_view, :assignment_note, false) do
|
||||
object.topic.assignment.note
|
||||
end
|
||||
add_to_serializer(:topic_view, :assignment_note, false) { object.topic.assignment.note }
|
||||
|
||||
add_to_serializer(:topic_view, :include_assignment_note?, false) do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.topic.assignment.present?
|
||||
|
@ -559,7 +618,7 @@ after_initialize do
|
|||
DiscourseAssign::Helpers.build_assigned_to_user(object.assigned_to, object)
|
||||
end
|
||||
|
||||
add_to_serializer(:search_topic_list_item, 'include_assigned_to_user?') do
|
||||
add_to_serializer(:search_topic_list_item, "include_assigned_to_user?") do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.assigned_to&.is_a?(User)
|
||||
end
|
||||
|
||||
|
@ -567,7 +626,7 @@ after_initialize do
|
|||
BasicGroupSerializer.new(object.assigned_to, scope: scope, root: false).as_json
|
||||
end
|
||||
|
||||
add_to_serializer(:search_topic_list_item, 'include_assigned_to_group?') do
|
||||
add_to_serializer(:search_topic_list_item, "include_assigned_to_group?") do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.assigned_to&.is_a?(Group)
|
||||
end
|
||||
|
||||
|
@ -583,30 +642,25 @@ after_initialize do
|
|||
TopicsBulkAction.register_operation("assign") do
|
||||
if @user.can_assign?
|
||||
assign_user = User.find_by_username(@operation[:username])
|
||||
topics.each do |topic|
|
||||
Assigner.new(topic, @user).assign(assign_user)
|
||||
end
|
||||
topics.each { |topic| Assigner.new(topic, @user).assign(assign_user) }
|
||||
end
|
||||
end
|
||||
|
||||
TopicsBulkAction.register_operation("unassign") do
|
||||
if @user.can_assign?
|
||||
topics.each do |topic|
|
||||
if guardian.can_assign?
|
||||
Assigner.new(topic, @user).unassign
|
||||
end
|
||||
end
|
||||
topics.each { |topic| Assigner.new(topic, @user).unassign if guardian.can_assign? }
|
||||
end
|
||||
end
|
||||
|
||||
register_permitted_bulk_action_parameter :username
|
||||
|
||||
add_to_class(:user_bookmark_base_serializer, :assigned_to) do
|
||||
@assigned_to ||= bookmarkable_type == "Topic" ? bookmarkable.assigned_to : bookmarkable.topic.assigned_to
|
||||
@assigned_to ||=
|
||||
bookmarkable_type == "Topic" ? bookmarkable.assigned_to : bookmarkable.topic.assigned_to
|
||||
end
|
||||
|
||||
add_to_class(:user_bookmark_base_serializer, :can_have_assignment?) do
|
||||
["Post", "Topic"].include?(bookmarkable_type)
|
||||
%w[Post Topic].include?(bookmarkable_type)
|
||||
end
|
||||
|
||||
add_to_serializer(:user_bookmark_base, :assigned_to_user, false) do
|
||||
|
@ -614,7 +668,7 @@ after_initialize do
|
|||
BasicUserSerializer.new(assigned_to, scope: scope, root: false).as_json
|
||||
end
|
||||
|
||||
add_to_serializer(:user_bookmark_base, 'include_assigned_to_user?') do
|
||||
add_to_serializer(:user_bookmark_base, "include_assigned_to_user?") do
|
||||
return false if !can_have_assignment?
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && assigned_to&.is_a?(User)
|
||||
end
|
||||
|
@ -624,56 +678,48 @@ after_initialize do
|
|||
BasicGroupSerializer.new(assigned_to, scope: scope, root: false).as_json
|
||||
end
|
||||
|
||||
add_to_serializer(:user_bookmark_base, 'include_assigned_to_group?') do
|
||||
add_to_serializer(:user_bookmark_base, "include_assigned_to_group?") do
|
||||
return false if !can_have_assignment?
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && assigned_to&.is_a?(Group)
|
||||
end
|
||||
|
||||
add_to_serializer(:basic_user, :assign_icon) do
|
||||
'user-plus'
|
||||
end
|
||||
add_to_serializer(:basic_user, :assign_icon) { "user-plus" }
|
||||
add_to_serializer(:basic_user, :assign_path) do
|
||||
return if !object.is_a?(User)
|
||||
SiteSetting.assigns_user_url_path.gsub("{username}", object.username)
|
||||
end
|
||||
|
||||
add_to_serializer(:basic_group, :assign_icon) do
|
||||
'group-plus'
|
||||
end
|
||||
add_to_serializer(:basic_group, :assign_icon) { "group-plus" }
|
||||
|
||||
add_to_serializer(:basic_group, :assign_path) do
|
||||
"/g/#{object.name}/assigned/everyone"
|
||||
end
|
||||
add_to_serializer(:basic_group, :assign_path) { "/g/#{object.name}/assigned/everyone" }
|
||||
|
||||
# PostSerializer
|
||||
add_to_serializer(:post, :assigned_to_user) do
|
||||
BasicUserSerializer.new(object.assignment.assigned_to, scope: scope, root: false).as_json
|
||||
end
|
||||
|
||||
add_to_serializer(:post, 'include_assigned_to_user?') do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.assignment&.assigned_to&.is_a?(User) && object.assignment.active
|
||||
add_to_serializer(:post, "include_assigned_to_user?") do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) &&
|
||||
object.assignment&.assigned_to&.is_a?(User) && object.assignment.active
|
||||
end
|
||||
|
||||
add_to_serializer(:post, :assigned_to_group, false) do
|
||||
BasicGroupSerializer.new(object.assignment.assigned_to, scope: scope, root: false).as_json
|
||||
end
|
||||
|
||||
add_to_serializer(:post, 'include_assigned_to_group?') do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.assignment&.assigned_to&.is_a?(Group) && object.assignment.active
|
||||
add_to_serializer(:post, "include_assigned_to_group?") do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) &&
|
||||
object.assignment&.assigned_to&.is_a?(Group) && object.assignment.active
|
||||
end
|
||||
|
||||
add_to_serializer(:post, :assignment_note, false) do
|
||||
object.assignment.note
|
||||
end
|
||||
add_to_serializer(:post, :assignment_note, false) { object.assignment.note }
|
||||
|
||||
add_to_serializer(:post, :include_assignment_note?, false) do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && object.assignment.present?
|
||||
end
|
||||
|
||||
# CurrentUser serializer
|
||||
add_to_serializer(:current_user, :can_assign) do
|
||||
object.can_assign?
|
||||
end
|
||||
add_to_serializer(:current_user, :can_assign) { object.can_assign? }
|
||||
|
||||
# FlaggedTopic serializer
|
||||
add_to_serializer(:flagged_topic, :assigned_to_user) do
|
||||
|
@ -697,59 +743,47 @@ after_initialize do
|
|||
[
|
||||
:assigned_to,
|
||||
Proc.new do |results, value|
|
||||
results.joins(<<~SQL
|
||||
results.joins(<<~SQL).where(target_type: Post.name).where("u.username = ?", value)
|
||||
INNER JOIN posts p ON p.id = target_id
|
||||
INNER JOIN topics t ON t.id = p.topic_id
|
||||
INNER JOIN assignments a ON a.topic_id = t.id AND a.assigned_to_type = 'User'
|
||||
INNER JOIN users u ON u.id = a.assigned_to_id
|
||||
SQL
|
||||
)
|
||||
.where(target_type: Post.name)
|
||||
.where('u.username = ?', value)
|
||||
end
|
||||
]
|
||||
end,
|
||||
],
|
||||
)
|
||||
|
||||
# TopicTrackingState
|
||||
add_class_method(:topic_tracking_state, :publish_assigned_private_message) do |topic, assignee|
|
||||
return unless topic.private_message?
|
||||
opts =
|
||||
if assignee.is_a?(User)
|
||||
{ user_ids: [assignee.id] }
|
||||
else
|
||||
{ group_ids: [assignee.id] }
|
||||
end
|
||||
opts = (assignee.is_a?(User) ? { user_ids: [assignee.id] } : { group_ids: [assignee.id] })
|
||||
|
||||
MessageBus.publish(
|
||||
"/private-messages/assigned",
|
||||
{ topic_id: topic.id },
|
||||
opts
|
||||
)
|
||||
MessageBus.publish("/private-messages/assigned", { topic_id: topic.id }, opts)
|
||||
end
|
||||
|
||||
# Event listeners
|
||||
on(:post_created) do |post|
|
||||
::Assigner.auto_assign(post, force: true)
|
||||
end
|
||||
on(:post_created) { |post| ::Assigner.auto_assign(post, force: true) }
|
||||
|
||||
on(:post_edited) do |post, topic_changed|
|
||||
::Assigner.auto_assign(post, force: true)
|
||||
end
|
||||
on(:post_edited) { |post, topic_changed| ::Assigner.auto_assign(post, force: true) }
|
||||
|
||||
on(:topic_status_updated) do |topic, status, enabled|
|
||||
if SiteSetting.unassign_on_close && (status == 'closed' || status == 'autoclosed') && enabled && Assignment.exists?(topic_id: topic.id, active: true)
|
||||
|
||||
if SiteSetting.unassign_on_close && (status == "closed" || status == "autoclosed") && enabled &&
|
||||
Assignment.exists?(topic_id: topic.id, active: true)
|
||||
assigner = ::Assigner.new(topic, Discourse.system_user)
|
||||
assigner.unassign(silent: true, deactivate: true)
|
||||
|
||||
topic.posts.joins(:assignment).find_each do |post|
|
||||
assigner = ::Assigner.new(post, Discourse.system_user)
|
||||
assigner.unassign(silent: true, deactivate: true)
|
||||
end
|
||||
topic
|
||||
.posts
|
||||
.joins(:assignment)
|
||||
.find_each do |post|
|
||||
assigner = ::Assigner.new(post, Discourse.system_user)
|
||||
assigner.unassign(silent: true, deactivate: true)
|
||||
end
|
||||
MessageBus.publish("/topic/#{topic.id}", reload_topic: true, refresh_stream: true)
|
||||
end
|
||||
|
||||
if SiteSetting.reassign_on_open && (status == 'closed' || status == 'autoclosed') && !enabled && Assignment.exists?(topic_id: topic.id, active: false)
|
||||
if SiteSetting.reassign_on_open && (status == "closed" || status == "autoclosed") && !enabled &&
|
||||
Assignment.exists?(topic_id: topic.id, active: false)
|
||||
Assignment.where(topic_id: topic.id, target_type: "Topic").update_all(active: true)
|
||||
Assignment
|
||||
.where(topic_id: topic.id, target_type: "Post")
|
||||
|
@ -766,14 +800,21 @@ after_initialize do
|
|||
end
|
||||
|
||||
# small actions have to be destroyed as link is incorrect
|
||||
PostCustomField.where(name: "action_code_post_id", value: post.id).find_each do |post_custom_field|
|
||||
next if ![Post.types[:small_action], Post.types[:whisper]].include?(post_custom_field.post.post_type)
|
||||
post_custom_field.post.destroy
|
||||
end
|
||||
PostCustomField
|
||||
.where(name: "action_code_post_id", value: post.id)
|
||||
.find_each do |post_custom_field|
|
||||
if ![Post.types[:small_action], Post.types[:whisper]].include?(
|
||||
post_custom_field.post.post_type,
|
||||
)
|
||||
next
|
||||
end
|
||||
post_custom_field.post.destroy
|
||||
end
|
||||
end
|
||||
|
||||
on(:post_recovered) do |post|
|
||||
if SiteSetting.reassign_on_open && Assignment.where(target_type: "Post", target_id: post.id, active: false)
|
||||
if SiteSetting.reassign_on_open &&
|
||||
Assignment.where(target_type: "Post", target_id: post.id, active: false)
|
||||
Assignment.where(target_type: "Post", target_id: post.id).update_all(active: true)
|
||||
MessageBus.publish("/topic/#{post.topic_id}", reload_topic: true, refresh_stream: true)
|
||||
end
|
||||
|
@ -782,22 +823,28 @@ after_initialize do
|
|||
on(:move_to_inbox) do |info|
|
||||
topic = info[:topic]
|
||||
|
||||
TopicTrackingState.publish_assigned_private_message(topic, topic.assignment.assigned_to) if topic.assignment
|
||||
if topic.assignment
|
||||
TopicTrackingState.publish_assigned_private_message(topic, topic.assignment.assigned_to)
|
||||
end
|
||||
|
||||
next if !SiteSetting.unassign_on_group_archive
|
||||
next if !info[:group]
|
||||
|
||||
Assignment.where(topic_id: topic.id, active: false).find_each do |assignment|
|
||||
next unless assignment.target
|
||||
assignment.update!(active: true)
|
||||
Jobs.enqueue(:assign_notification,
|
||||
topic_id: topic.id,
|
||||
post_id: assignment.target_type.is_a?(Topic) ? topic.first_post.id : assignment.target.id,
|
||||
assigned_to_id: assignment.assigned_to_id,
|
||||
assigned_to_type: assignment.assigned_to_type,
|
||||
assigned_by_id: assignment.assigned_by_user_id,
|
||||
skip_small_action_post: true)
|
||||
end
|
||||
Assignment
|
||||
.where(topic_id: topic.id, active: false)
|
||||
.find_each do |assignment|
|
||||
next unless assignment.target
|
||||
assignment.update!(active: true)
|
||||
Jobs.enqueue(
|
||||
:assign_notification,
|
||||
topic_id: topic.id,
|
||||
post_id: assignment.target_type.is_a?(Topic) ? topic.first_post.id : assignment.target.id,
|
||||
assigned_to_id: assignment.assigned_to_id,
|
||||
assigned_to_type: assignment.assigned_to_type,
|
||||
assigned_by_id: assignment.assigned_by_user_id,
|
||||
skip_small_action_post: true,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
on(:archive_message) do |info|
|
||||
|
@ -809,33 +856,36 @@ after_initialize do
|
|||
next if !SiteSetting.unassign_on_group_archive
|
||||
next if !info[:group]
|
||||
|
||||
Assignment.where(topic_id: topic.id, active: true).find_each do |assignment|
|
||||
assignment.update!(active: false)
|
||||
Jobs.enqueue(:unassign_notification,
|
||||
topic_id: topic.id,
|
||||
assigned_to_id: assignment.assigned_to.id,
|
||||
assigned_to_type: assignment.assigned_to_type)
|
||||
end
|
||||
Assignment
|
||||
.where(topic_id: topic.id, active: true)
|
||||
.find_each do |assignment|
|
||||
assignment.update!(active: false)
|
||||
Jobs.enqueue(
|
||||
:unassign_notification,
|
||||
topic_id: topic.id,
|
||||
assigned_to_id: assignment.assigned_to.id,
|
||||
assigned_to_type: assignment.assigned_to_type,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
on(:user_removed_from_group) do |user, group|
|
||||
assign_allowed_groups = SiteSetting.assign_allowed_on_groups.split('|').map(&:to_i)
|
||||
assign_allowed_groups = SiteSetting.assign_allowed_on_groups.split("|").map(&:to_i)
|
||||
|
||||
if assign_allowed_groups.include?(group.id)
|
||||
groups = GroupUser.where(user: user).pluck(:group_id)
|
||||
|
||||
if (groups & assign_allowed_groups).empty?
|
||||
topics = Topic.joins(:assignment).where('assignments.assigned_to_id = ?', user.id)
|
||||
topics = Topic.joins(:assignment).where("assignments.assigned_to_id = ?", user.id)
|
||||
|
||||
topics.each do |topic|
|
||||
Assigner.new(topic, Discourse.system_user).unassign
|
||||
end
|
||||
topics.each { |topic| Assigner.new(topic, Discourse.system_user).unassign }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on(:post_moved) do |post, original_topic_id|
|
||||
assignment = Assignment.where(topic_id: original_topic_id, target_type: "Post", target_id: post.id).first
|
||||
assignment =
|
||||
Assignment.where(topic_id: original_topic_id, target_type: "Post", target_id: post.id).first
|
||||
next if !assignment
|
||||
if post.is_first_post?
|
||||
assignment.update!(topic_id: post.topic_id, target_type: "Topic", target_id: post.topic_id)
|
||||
|
@ -846,32 +896,24 @@ after_initialize do
|
|||
|
||||
class ::WebHook
|
||||
def self.enqueue_assign_hooks(event, payload)
|
||||
if active_web_hooks('assign').exists?
|
||||
WebHook.enqueue_hooks(:assign, event,
|
||||
payload: payload
|
||||
)
|
||||
end
|
||||
WebHook.enqueue_hooks(:assign, event, payload: payload) if active_web_hooks("assign").exists?
|
||||
end
|
||||
end
|
||||
|
||||
register_search_advanced_filter(/in:assigned/) do |posts|
|
||||
if @guardian.can_assign?
|
||||
posts.where(<<~SQL)
|
||||
posts.where(<<~SQL) if @guardian.can_assign?
|
||||
topics.id IN (
|
||||
SELECT a.topic_id FROM assignments a WHERE a.active
|
||||
)
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
register_search_advanced_filter(/in:unassigned/) do |posts|
|
||||
if @guardian.can_assign?
|
||||
posts.where(<<~SQL)
|
||||
posts.where(<<~SQL) if @guardian.can_assign?
|
||||
topics.id NOT IN (
|
||||
SELECT a.topic_id FROM assignments a WHERE a.active
|
||||
)
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
register_search_advanced_filter(/assigned:(.+)$/) do |posts, match|
|
||||
|
@ -893,9 +935,9 @@ after_initialize do
|
|||
end
|
||||
|
||||
if defined?(DiscourseAutomation)
|
||||
require 'random_assign_utils'
|
||||
require "random_assign_utils"
|
||||
|
||||
add_automation_scriptable('random_assign') do
|
||||
add_automation_scriptable("random_assign") do
|
||||
field :assignees_group, component: :group, required: true
|
||||
field :assigned_topic, component: :text, required: true
|
||||
field :minimum_time_between_assignments, component: :text
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe Search do
|
||||
fab!(:user) { Fabricate(:active_user) }
|
||||
|
@ -12,8 +12,8 @@ describe Search do
|
|||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
|
||||
context 'Advanced search' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
context "Advanced search" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
let(:post1) { Fabricate(:post) }
|
||||
let(:post2) { Fabricate(:post) }
|
||||
|
@ -30,34 +30,47 @@ describe Search do
|
|||
Assigner.new(post2.topic, user).assign(user2)
|
||||
Assigner.new(post3.topic, user).assign(user)
|
||||
Assigner.new(post5, user).assign(user)
|
||||
Assignment.create!(assigned_to: user, assigned_by_user: user, target: post6, topic_id: post6.topic.id, active: false)
|
||||
Assignment.create!(
|
||||
assigned_to: user,
|
||||
assigned_by_user: user,
|
||||
target: post6,
|
||||
topic_id: post6.topic.id,
|
||||
active: false,
|
||||
)
|
||||
end
|
||||
|
||||
it 'can find by status' do
|
||||
expect(Search.execute('in:assigned', guardian: Guardian.new(user)).posts.length).to eq(4)
|
||||
it "can find by status" do
|
||||
expect(Search.execute("in:assigned", guardian: Guardian.new(user)).posts.length).to eq(4)
|
||||
|
||||
Assigner.new(post3.topic, user).unassign
|
||||
|
||||
expect(Search.execute('in:unassigned', guardian: Guardian.new(user)).posts.length).to eq(2)
|
||||
expect(Search.execute("assigned:#{user.username}", guardian: Guardian.new(user)).posts.length).to eq(2)
|
||||
expect(Search.execute("in:unassigned", guardian: Guardian.new(user)).posts.length).to eq(2)
|
||||
expect(
|
||||
Search.execute("assigned:#{user.username}", guardian: Guardian.new(user)).posts.length,
|
||||
).to eq(2)
|
||||
end
|
||||
|
||||
it 'serializes results' do
|
||||
it "serializes results" do
|
||||
guardian = Guardian.new(user)
|
||||
result = Search.execute('in:assigned', guardian: guardian)
|
||||
result = Search.execute("in:assigned", guardian: guardian)
|
||||
serializer = GroupedSearchResultSerializer.new(result, scope: guardian)
|
||||
indirectly_assigned_to = serializer.as_json[:topics].find { |topic| topic[:id] == post5.topic.id }[:indirectly_assigned_to]
|
||||
expect(indirectly_assigned_to).to eq(post5.id => {
|
||||
assigned_to: {
|
||||
assign_icon: "user-plus",
|
||||
assign_path: "/u/#{user.username}/activity/assigned",
|
||||
avatar_template: user.avatar_template,
|
||||
name: user.name,
|
||||
username: user.username,
|
||||
indirectly_assigned_to =
|
||||
serializer.as_json[:topics].find { |topic| topic[:id] == post5.topic.id }[
|
||||
:indirectly_assigned_to
|
||||
]
|
||||
expect(indirectly_assigned_to).to eq(
|
||||
post5.id => {
|
||||
assigned_to: {
|
||||
assign_icon: "user-plus",
|
||||
assign_path: "/u/#{user.username}/activity/assigned",
|
||||
avatar_template: user.avatar_template,
|
||||
name: user.name,
|
||||
username: user.username,
|
||||
},
|
||||
post_number: post5.post_number,
|
||||
assignment_note: nil,
|
||||
},
|
||||
post_number: post5.post_number,
|
||||
assignment_note: nil,
|
||||
})
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,27 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe TopicQuery do
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:user2) { Fabricate(:user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user)
|
||||
add_to_assign_allowed_group(user2)
|
||||
end
|
||||
|
||||
describe '#list_messages_assigned' do
|
||||
fab!(:private_message) do
|
||||
Fabricate(:private_message_post, user: user).topic
|
||||
end
|
||||
describe "#list_messages_assigned" do
|
||||
fab!(:private_message) { Fabricate(:private_message_post, user: user).topic }
|
||||
|
||||
fab!(:topic) { Fabricate(:post, user: user).topic }
|
||||
fab!(:group_topic) { Fabricate(:post, user: user).topic }
|
||||
|
@ -32,13 +28,13 @@ describe TopicQuery do
|
|||
assign_to(group_topic, user, assign_allowed_group)
|
||||
end
|
||||
|
||||
it 'Includes topics and PMs assigned to user' do
|
||||
it "Includes topics and PMs assigned to user" do
|
||||
assigned_messages = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
||||
expect(assigned_messages).to contain_exactly(private_message, topic, group_topic)
|
||||
end
|
||||
|
||||
it 'Excludes inactive assignments' do
|
||||
it "Excludes inactive assignments" do
|
||||
Assignment.update_all(active: false)
|
||||
|
||||
assigned_messages = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
@ -46,19 +42,20 @@ describe TopicQuery do
|
|||
expect(assigned_messages).to eq([])
|
||||
end
|
||||
|
||||
it 'Excludes topics and PMs not assigned to user' do
|
||||
it "Excludes topics and PMs not assigned to user" do
|
||||
assigned_messages = TopicQuery.new(user2, { page: 0 }).list_messages_assigned(user2).topics
|
||||
|
||||
expect(assigned_messages).to contain_exactly(group_topic)
|
||||
end
|
||||
|
||||
it 'direct filter excludes group assignment' do
|
||||
assigned_messages = TopicQuery.new(user, { page: 0, filter: :direct }).list_messages_assigned(user).topics
|
||||
it "direct filter excludes group assignment" do
|
||||
assigned_messages =
|
||||
TopicQuery.new(user, { page: 0, filter: :direct }).list_messages_assigned(user).topics
|
||||
|
||||
expect(assigned_messages).to contain_exactly(private_message, topic)
|
||||
end
|
||||
|
||||
it 'Returns the results ordered by the bumped_at field' do
|
||||
it "Returns the results ordered by the bumped_at field" do
|
||||
topic.update(bumped_at: 2.weeks.ago)
|
||||
|
||||
assigned_messages = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
@ -67,11 +64,8 @@ describe TopicQuery do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#list_group_topics_assigned' do
|
||||
|
||||
fab!(:private_message) do
|
||||
Fabricate(:private_message_post, user: user).topic
|
||||
end
|
||||
describe "#list_group_topics_assigned" do
|
||||
fab!(:private_message) { Fabricate(:private_message_post, user: user).topic }
|
||||
|
||||
fab!(:topic) { Fabricate(:post, user: user).topic }
|
||||
|
||||
|
@ -83,34 +77,41 @@ describe TopicQuery do
|
|||
assign_to(group_topic, user, assign_allowed_group)
|
||||
end
|
||||
|
||||
it 'Includes topics and PMs assigned to user' do
|
||||
assigned_messages = TopicQuery.new(user, { page: 0 }).list_group_topics_assigned(assign_allowed_group).topics
|
||||
it "Includes topics and PMs assigned to user" do
|
||||
assigned_messages =
|
||||
TopicQuery.new(user, { page: 0 }).list_group_topics_assigned(assign_allowed_group).topics
|
||||
|
||||
expect(assigned_messages).to contain_exactly(private_message, topic, group_topic)
|
||||
end
|
||||
|
||||
it 'Returns the results ordered by the bumped_at field' do
|
||||
it "Returns the results ordered by the bumped_at field" do
|
||||
topic.update(bumped_at: 2.weeks.ago)
|
||||
|
||||
assigned_messages = TopicQuery.new(user, { page: 0 }).list_group_topics_assigned(assign_allowed_group).topics
|
||||
assigned_messages =
|
||||
TopicQuery.new(user, { page: 0 }).list_group_topics_assigned(assign_allowed_group).topics
|
||||
|
||||
expect(assigned_messages).to eq([group_topic, private_message, topic])
|
||||
end
|
||||
|
||||
it 'direct filter shows only group assignments' do
|
||||
assigned_messages = TopicQuery.new(user, { page: 0, filter: :direct }).list_group_topics_assigned(assign_allowed_group).topics
|
||||
it "direct filter shows only group assignments" do
|
||||
assigned_messages =
|
||||
TopicQuery
|
||||
.new(user, { page: 0, filter: :direct })
|
||||
.list_group_topics_assigned(assign_allowed_group)
|
||||
.topics
|
||||
|
||||
expect(assigned_messages).to contain_exactly(group_topic)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#list_private_messages_assigned' do
|
||||
describe "#list_private_messages_assigned" do
|
||||
let(:user_topic) do
|
||||
topic = create_post(
|
||||
user: Fabricate(:user),
|
||||
target_usernames: [user.username, user2.username],
|
||||
archetype: Archetype.private_message
|
||||
).topic
|
||||
topic =
|
||||
create_post(
|
||||
user: Fabricate(:user),
|
||||
target_usernames: [user.username, user2.username],
|
||||
archetype: Archetype.private_message,
|
||||
).topic
|
||||
|
||||
create_post(topic_id: topic.id, user: user)
|
||||
|
||||
|
@ -118,61 +119,63 @@ describe TopicQuery do
|
|||
end
|
||||
|
||||
let(:assigned_topic) do
|
||||
topic = create_post(
|
||||
user: Fabricate(:user),
|
||||
target_usernames: [user.username, user2.username],
|
||||
archetype: Archetype.private_message
|
||||
).topic
|
||||
topic =
|
||||
create_post(
|
||||
user: Fabricate(:user),
|
||||
target_usernames: [user.username, user2.username],
|
||||
archetype: Archetype.private_message,
|
||||
).topic
|
||||
|
||||
assign_to(topic, user, user)
|
||||
end
|
||||
|
||||
let(:group2) do
|
||||
Fabricate(:group, messageable_level: Group::ALIAS_LEVELS[:everyone])
|
||||
end
|
||||
let(:group2) { Fabricate(:group, messageable_level: Group::ALIAS_LEVELS[:everyone]) }
|
||||
|
||||
let(:group_assigned_topic) do
|
||||
topic = create_post(
|
||||
user: user,
|
||||
target_group_names: [assign_allowed_group.name, group2.name],
|
||||
archetype: Archetype.private_message
|
||||
).topic
|
||||
topic =
|
||||
create_post(
|
||||
user: user,
|
||||
target_group_names: [assign_allowed_group.name, group2.name],
|
||||
archetype: Archetype.private_message,
|
||||
).topic
|
||||
|
||||
assign_to(topic, user, user)
|
||||
end
|
||||
|
||||
before do
|
||||
assign_allowed_group.update!(
|
||||
messageable_level: Group::ALIAS_LEVELS[:everyone]
|
||||
)
|
||||
assign_allowed_group.update!(messageable_level: Group::ALIAS_LEVELS[:everyone])
|
||||
|
||||
user_topic
|
||||
assigned_topic
|
||||
group_assigned_topic
|
||||
end
|
||||
|
||||
it 'should return the right topics' do
|
||||
expect(
|
||||
TopicQuery.new(user).list_private_messages_assigned(user).topics
|
||||
).to contain_exactly(assigned_topic, group_assigned_topic)
|
||||
it "should return the right topics" do
|
||||
expect(TopicQuery.new(user).list_private_messages_assigned(user).topics).to contain_exactly(
|
||||
assigned_topic,
|
||||
group_assigned_topic,
|
||||
)
|
||||
|
||||
UserArchivedMessage.archive!(user.id, assigned_topic)
|
||||
|
||||
expect(
|
||||
TopicQuery.new(user).list_private_messages_assigned(user).topics
|
||||
).to contain_exactly(assigned_topic, group_assigned_topic)
|
||||
expect(TopicQuery.new(user).list_private_messages_assigned(user).topics).to contain_exactly(
|
||||
assigned_topic,
|
||||
group_assigned_topic,
|
||||
)
|
||||
|
||||
GroupArchivedMessage.archive!(group2.id, group_assigned_topic)
|
||||
|
||||
expect(
|
||||
TopicQuery.new(user).list_private_messages_assigned(user).topics
|
||||
).to contain_exactly(assigned_topic, group_assigned_topic)
|
||||
expect(TopicQuery.new(user).list_private_messages_assigned(user).topics).to contain_exactly(
|
||||
assigned_topic,
|
||||
group_assigned_topic,
|
||||
)
|
||||
|
||||
GroupArchivedMessage.archive!(assign_allowed_group.id, group_assigned_topic)
|
||||
|
||||
expect(
|
||||
TopicQuery.new(user).list_private_messages_assigned(user).topics
|
||||
).to contain_exactly(assigned_topic, group_assigned_topic)
|
||||
expect(TopicQuery.new(user).list_private_messages_assigned(user).topics).to contain_exactly(
|
||||
assigned_topic,
|
||||
group_assigned_topic,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -225,8 +228,6 @@ describe TopicQuery do
|
|||
end
|
||||
|
||||
def assign_to(topic, user, assignee)
|
||||
topic.tap do |t|
|
||||
Assigner.new(t, user).assign(assignee)
|
||||
end
|
||||
topic.tap { |t| Assigner.new(t, user).assign(assignee) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe TopicsBulkAction do
|
||||
fab!(:post) { Fabricate(:post) }
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:user2) { Fabricate(:user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user)
|
||||
end
|
||||
before { add_to_assign_allowed_group(user) }
|
||||
|
||||
describe "assign_topics" do
|
||||
it "assigns multiple topics to user" do
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id], { type: 'assign', username: user.username }).perform!
|
||||
TopicsBulkAction.new(
|
||||
user,
|
||||
[post.topic.id, post1.topic.id],
|
||||
{ type: "assign", username: user.username },
|
||||
).perform!
|
||||
|
||||
assigned_topics = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
||||
|
@ -33,7 +33,11 @@ describe TopicsBulkAction do
|
|||
end
|
||||
|
||||
it "doesn't allows to assign to user not in assign_allowed_group" do
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id], { type: 'assign', username: user2.username }).perform!
|
||||
TopicsBulkAction.new(
|
||||
user,
|
||||
[post.topic.id, post1.topic.id],
|
||||
{ type: "assign", username: user2.username },
|
||||
).perform!
|
||||
|
||||
assigned_topics = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user2).topics
|
||||
|
||||
|
@ -41,7 +45,11 @@ describe TopicsBulkAction do
|
|||
end
|
||||
|
||||
it "user who is not in assign_allowed_group can't assign topics" do
|
||||
TopicsBulkAction.new(user2, [post.topic.id, post1.topic.id, post2.topic.id], { type: 'assign', username: user.username }).perform!
|
||||
TopicsBulkAction.new(
|
||||
user2,
|
||||
[post.topic.id, post1.topic.id, post2.topic.id],
|
||||
{ type: "assign", username: user.username },
|
||||
).perform!
|
||||
|
||||
assigned_topics = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
||||
|
@ -51,9 +59,13 @@ describe TopicsBulkAction do
|
|||
|
||||
describe "unassign_topics" do
|
||||
it "unassigns multiple topics assigned to user" do
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id, post2.topic.id], { type: 'assign', username: user.username }).perform!
|
||||
TopicsBulkAction.new(
|
||||
user,
|
||||
[post.topic.id, post1.topic.id, post2.topic.id],
|
||||
{ type: "assign", username: user.username },
|
||||
).perform!
|
||||
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id], type: 'unassign').perform!
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id], type: "unassign").perform!
|
||||
|
||||
assigned_topics = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
||||
|
@ -63,9 +75,13 @@ describe TopicsBulkAction do
|
|||
end
|
||||
|
||||
it "user who is not in assign_allowed_group can't unassign topics" do
|
||||
TopicsBulkAction.new(user, [post.topic.id, post1.topic.id, post2.topic.id], { type: 'assign', username: user.username }).perform!
|
||||
TopicsBulkAction.new(
|
||||
user,
|
||||
[post.topic.id, post1.topic.id, post2.topic.id],
|
||||
{ type: "assign", username: user.username },
|
||||
).perform!
|
||||
|
||||
TopicsBulkAction.new(user2, [post.topic.id, post1.topic.id], type: 'unassign').perform!
|
||||
TopicsBulkAction.new(user2, [post.topic.id, post1.topic.id], type: "unassign").perform!
|
||||
|
||||
assigned_topics = TopicQuery.new(user, { page: 0 }).list_messages_assigned(user).topics
|
||||
|
||||
|
@ -73,6 +89,5 @@ describe TopicsBulkAction do
|
|||
|
||||
expect(assigned_topics).to contain_exactly(post.topic, post1.topic, post2.topic)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:assign_web_hook, from: :web_hook) do
|
||||
transient assign_hook: WebHookEventType.find_by(name: 'assign')
|
||||
transient assign_hook: WebHookEventType.find_by(name: "assign")
|
||||
|
||||
after_build do |web_hook, transients|
|
||||
web_hook.web_hook_event_types = [transients[:assign_hook]]
|
||||
end
|
||||
after_build { |web_hook, transients| web_hook.web_hook_event_types = [transients[:assign_hook]] }
|
||||
end
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require_relative '../fabricators/assign_hook_fabricator.rb'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
require_relative "../fabricators/assign_hook_fabricator.rb"
|
||||
|
||||
describe 'integration tests' do
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
describe "integration tests" do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
it 'preloads data in topic list' do
|
||||
it "preloads data in topic list" do
|
||||
admin = Fabricate(:admin)
|
||||
post = create_post
|
||||
list = TopicList.new("latest", admin, [post.topic])
|
||||
|
@ -17,7 +15,7 @@ describe 'integration tests' do
|
|||
# should not explode for now
|
||||
end
|
||||
|
||||
describe 'for a private message' do
|
||||
describe "for a private message" do
|
||||
let(:post) { Fabricate(:private_message_post) }
|
||||
let(:pm) { post.topic }
|
||||
let(:user) { pm.allowed_users.first }
|
||||
|
@ -25,7 +23,7 @@ describe 'integration tests' do
|
|||
let(:channel) { "/private-messages/assigned" }
|
||||
fab!(:group) { Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:everyone]) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user)
|
||||
|
@ -35,9 +33,7 @@ describe 'integration tests' do
|
|||
end
|
||||
|
||||
def assert_publish_topic_state(topic, user: nil, group: nil)
|
||||
messages = MessageBus.track_publish do
|
||||
yield
|
||||
end
|
||||
messages = MessageBus.track_publish { yield }
|
||||
|
||||
message = messages.find { |m| m.channel == channel }
|
||||
|
||||
|
@ -46,7 +42,7 @@ describe 'integration tests' do
|
|||
expect(message.group_ids).to eq([group.id]) if group
|
||||
end
|
||||
|
||||
it 'publishes the right message on archive and move to inbox' do
|
||||
it "publishes the right message on archive and move to inbox" do
|
||||
assigner = Assigner.new(pm, user)
|
||||
assigner.assign(user)
|
||||
|
||||
|
@ -59,7 +55,7 @@ describe 'integration tests' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'publishes the right message on archive and move to inbox for groups' do
|
||||
it "publishes the right message on archive and move to inbox for groups" do
|
||||
assigner = Assigner.new(pm, user)
|
||||
assigner.assign(group)
|
||||
|
||||
|
@ -106,7 +102,7 @@ describe 'integration tests' do
|
|||
let(:user1) { Fabricate(:user) }
|
||||
let(:user2) { Fabricate(:user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user1)
|
||||
|
@ -142,15 +138,15 @@ describe 'integration tests' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'already assigned' do
|
||||
context "already assigned" do
|
||||
fab!(:post) { Fabricate(:post) }
|
||||
fab!(:post_2) { Fabricate(:post, topic: post.topic) }
|
||||
let(:topic) { post.topic }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
it 'does not allow to assign topic if post is already assigned' do
|
||||
it "does not allow to assign topic if post is already assigned" do
|
||||
add_to_assign_allowed_group(user)
|
||||
|
||||
assigner = Assigner.new(post, user)
|
||||
|
@ -168,14 +164,22 @@ describe 'integration tests' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'move post' do
|
||||
context "move post" do
|
||||
fab!(:old_topic) { Fabricate(:topic) }
|
||||
fab!(:post) { Fabricate(:post, topic: old_topic) }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:assignment) { Assignment.create!(target_id: post.id, target_type: "Post", topic_id: old_topic.id, assigned_by_user: user, assigned_to: user) }
|
||||
fab!(:assignment) do
|
||||
Assignment.create!(
|
||||
target_id: post.id,
|
||||
target_type: "Post",
|
||||
topic_id: old_topic.id,
|
||||
assigned_by_user: user,
|
||||
assigned_to: user,
|
||||
)
|
||||
end
|
||||
let(:new_topic) { Fabricate(:topic) }
|
||||
|
||||
it 'assignment becomes topic assignment when new topic' do
|
||||
it "assignment becomes topic assignment when new topic" do
|
||||
post.update!(topic: new_topic)
|
||||
DiscourseEvent.trigger(:post_moved, post, old_topic.id)
|
||||
assignment.reload
|
||||
|
@ -184,7 +188,7 @@ describe 'integration tests' do
|
|||
expect(assignment.target_id).to eq(new_topic.id)
|
||||
end
|
||||
|
||||
it 'assigment is still post assignment when not first post' do
|
||||
it "assigment is still post assignment when not first post" do
|
||||
post.update!(topic: new_topic, post_number: "3")
|
||||
DiscourseEvent.trigger(:post_moved, post, old_topic.id)
|
||||
assignment.reload
|
||||
|
|
|
@ -1,51 +1,65 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Jobs::AssignNotification do
|
||||
describe '#execute' do
|
||||
describe "#execute" do
|
||||
fab!(:user1) { Fabricate(:user, last_seen_at: 1.day.ago) }
|
||||
fab!(:user2) { Fabricate(:user, last_seen_at: 1.day.ago) }
|
||||
fab!(:topic) { Fabricate(:topic, title: 'Basic topic title') }
|
||||
fab!(:topic) { Fabricate(:topic, title: "Basic topic title") }
|
||||
fab!(:post) { Fabricate(:post, topic: topic) }
|
||||
fab!(:pm_post) { Fabricate(:private_message_post) }
|
||||
fab!(:pm) { pm_post.topic }
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
|
||||
def assert_publish_topic_state(topic, user)
|
||||
message = MessageBus.track_publish('/private-messages/assigned') do
|
||||
yield
|
||||
end.first
|
||||
message = MessageBus.track_publish("/private-messages/assigned") { yield }.first
|
||||
|
||||
expect(message.data[:topic_id]).to eq(topic.id)
|
||||
expect(message.user_ids).to eq([user.id])
|
||||
end
|
||||
|
||||
before do
|
||||
assign_allowed_group.add(user1)
|
||||
end
|
||||
before { assign_allowed_group.add(user1) }
|
||||
|
||||
context 'User' do
|
||||
|
||||
it 'sends notification alert' do
|
||||
messages = MessageBus.track_publish("/notification-alert/#{user2.id}") do
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: user2.id, assigned_to_type: 'User', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
end
|
||||
context "User" do
|
||||
it "sends notification alert" do
|
||||
messages =
|
||||
MessageBus.track_publish("/notification-alert/#{user2.id}") do
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: user2.id,
|
||||
assigned_to_type: "User",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
expect(messages.length).to eq(1)
|
||||
expect(messages.first.data[:excerpt]).to eq("assigned you the topic 'Basic topic title'")
|
||||
end
|
||||
|
||||
it 'should publish the right message when private message' do
|
||||
it "should publish the right message when private message" do
|
||||
user = pm.allowed_users.first
|
||||
assign_allowed_group.add(user)
|
||||
|
||||
assert_publish_topic_state(pm, user) do
|
||||
described_class.new.execute({ topic_id: pm.id, post_id: pm_post.id, assigned_to_id: pm.allowed_users.first.id, assigned_to_type: 'User', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: pm.id,
|
||||
post_id: pm_post.id,
|
||||
assigned_to_id: pm.allowed_users.first.id,
|
||||
assigned_to_type: "User",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it 'sends a high priority notification to the assignee' do
|
||||
it "sends a high priority notification to the assignee" do
|
||||
Notification.expects(:create!).with(
|
||||
notification_type: Notification.types[:assigned] || Notification.types[:custom],
|
||||
user_id: user2.id,
|
||||
|
@ -53,20 +67,31 @@ RSpec.describe Jobs::AssignNotification do
|
|||
post_number: 1,
|
||||
high_priority: true,
|
||||
data: {
|
||||
message: 'discourse_assign.assign_notification',
|
||||
message: "discourse_assign.assign_notification",
|
||||
display_username: user1.username,
|
||||
topic_title: topic.title
|
||||
}.to_json
|
||||
topic_title: topic.title,
|
||||
}.to_json,
|
||||
)
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: user2.id,
|
||||
assigned_to_type: "User",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: user2.id, assigned_to_type: 'User', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
end
|
||||
end
|
||||
|
||||
context 'Group' do
|
||||
context "Group" do
|
||||
fab!(:user3) { Fabricate(:user, last_seen_at: 1.day.ago) }
|
||||
fab!(:user4) { Fabricate(:user, suspended_till: 1.year.from_now) }
|
||||
fab!(:group) { Fabricate(:group, name: 'Developers') }
|
||||
let(:assignment) { Assignment.create!(topic: topic, assigned_by_user: user1, assigned_to: group) }
|
||||
fab!(:group) { Fabricate(:group, name: "Developers") }
|
||||
let(:assignment) do
|
||||
Assignment.create!(topic: topic, assigned_by_user: user1, assigned_to: group)
|
||||
end
|
||||
|
||||
before do
|
||||
group.add(user2)
|
||||
|
@ -74,26 +99,60 @@ RSpec.describe Jobs::AssignNotification do
|
|||
group.add(user4)
|
||||
end
|
||||
|
||||
it 'sends notification alert to all group members' do
|
||||
messages = MessageBus.track_publish("/notification-alert/#{user2.id}") do
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
end
|
||||
it "sends notification alert to all group members" do
|
||||
messages =
|
||||
MessageBus.track_publish("/notification-alert/#{user2.id}") do
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
expect(messages.length).to eq(1)
|
||||
expect(messages.first.data[:excerpt]).to eq("assigned to Developers the topic 'Basic topic title'")
|
||||
expect(messages.first.data[:excerpt]).to eq(
|
||||
"assigned to Developers the topic 'Basic topic title'",
|
||||
)
|
||||
|
||||
messages = MessageBus.track_publish("/notification-alert/#{user3.id}") do
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
end
|
||||
messages =
|
||||
MessageBus.track_publish("/notification-alert/#{user3.id}") do
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
expect(messages.length).to eq(1)
|
||||
expect(messages.first.data[:excerpt]).to eq("assigned to Developers the topic 'Basic topic title'")
|
||||
expect(messages.first.data[:excerpt]).to eq(
|
||||
"assigned to Developers the topic 'Basic topic title'",
|
||||
)
|
||||
|
||||
messages = MessageBus.track_publish("/notification-alert/#{user4.id}") do
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
end
|
||||
messages =
|
||||
MessageBus.track_publish("/notification-alert/#{user4.id}") do
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
expect(messages.length).to eq(0)
|
||||
end
|
||||
|
||||
it 'sends a high priority notification to all group members' do
|
||||
it "sends a high priority notification to all group members" do
|
||||
[user2, user3, user4].each do |user|
|
||||
Notification.expects(:create!).with(
|
||||
notification_type: Notification.types[:assigned] || Notification.types[:custom],
|
||||
|
@ -102,14 +161,23 @@ RSpec.describe Jobs::AssignNotification do
|
|||
post_number: 1,
|
||||
high_priority: true,
|
||||
data: {
|
||||
message: 'discourse_assign.assign_group_notification',
|
||||
message: "discourse_assign.assign_group_notification",
|
||||
display_username: group.name,
|
||||
topic_title: topic.title
|
||||
}.to_json
|
||||
topic_title: topic.title,
|
||||
}.to_json,
|
||||
)
|
||||
end
|
||||
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Jobs::RemindUser do
|
||||
describe '#execute' do
|
||||
describe "#execute" do
|
||||
it "should raise the right error when user_id is invalid" do
|
||||
expect do
|
||||
described_class.new.execute({})
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
expect do described_class.new.execute({}) end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,51 +1,70 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Jobs::UnassignNotification do
|
||||
describe '#execute' do
|
||||
describe "#execute" do
|
||||
fab!(:user1) { Fabricate(:user) }
|
||||
fab!(:user2) { Fabricate(:user) }
|
||||
fab!(:topic) { Fabricate(:topic) }
|
||||
fab!(:post) { Fabricate(:post, topic: topic) }
|
||||
fab!(:pm_post) { Fabricate(:private_message_post) }
|
||||
fab!(:pm) { pm_post.topic }
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
|
||||
before do
|
||||
assign_allowed_group.add(user1)
|
||||
end
|
||||
before { assign_allowed_group.add(user1) }
|
||||
|
||||
def assert_publish_topic_state(topic, user)
|
||||
message = MessageBus.track_publish('/private-messages/assigned') do
|
||||
yield
|
||||
end.first
|
||||
message = MessageBus.track_publish("/private-messages/assigned") { yield }.first
|
||||
|
||||
expect(message.data[:topic_id]).to eq(topic.id)
|
||||
expect(message.user_ids).to eq([user.id])
|
||||
end
|
||||
|
||||
context 'User' do
|
||||
it 'deletes notifications' do
|
||||
Jobs::AssignNotification.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: user2.id, assigned_to_type: 'User', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
context "User" do
|
||||
it "deletes notifications" do
|
||||
Jobs::AssignNotification.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: user2.id,
|
||||
assigned_to_type: "User",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
|
||||
expect {
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: user2.id, assigned_to_type: 'User' })
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: user2.id,
|
||||
assigned_to_type: "User",
|
||||
},
|
||||
)
|
||||
}.to change { user2.notifications.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'should publish the right message when private message' do
|
||||
it "should publish the right message when private message" do
|
||||
user = pm.allowed_users.first
|
||||
assign_allowed_group.add(user)
|
||||
|
||||
assert_publish_topic_state(pm, user) do
|
||||
described_class.new.execute({ topic_id: pm.id, post_id: pm_post.id, assigned_to_id: pm.allowed_users.first.id, assigned_to_type: 'User' })
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: pm.id,
|
||||
post_id: pm_post.id,
|
||||
assigned_to_id: pm.allowed_users.first.id,
|
||||
assigned_to_type: "User",
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'Group' do
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
context "Group" do
|
||||
fab!(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
fab!(:user3) { Fabricate(:user) }
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
|
||||
|
@ -54,11 +73,27 @@ RSpec.describe Jobs::UnassignNotification do
|
|||
group.add(user3)
|
||||
end
|
||||
|
||||
it 'deletes notifications' do
|
||||
Jobs::AssignNotification.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group', assigned_by_id: user1.id, skip_small_action_post: false })
|
||||
it "deletes notifications" do
|
||||
Jobs::AssignNotification.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
assigned_by_id: user1.id,
|
||||
skip_small_action_post: false,
|
||||
},
|
||||
)
|
||||
|
||||
expect {
|
||||
described_class.new.execute({ topic_id: topic.id, post_id: post.id, assigned_to_id: group.id, assigned_to_type: 'Group' })
|
||||
described_class.new.execute(
|
||||
{
|
||||
topic_id: topic.id,
|
||||
post_id: post.id,
|
||||
assigned_to_id: group.id,
|
||||
assigned_to_type: "Group",
|
||||
},
|
||||
)
|
||||
}.to change { Notification.count }.by(-2)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Jobs::EnqueueReminders do
|
||||
let(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
let(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
let(:user) { Fabricate(:user, groups: [assign_allowed_group]) }
|
||||
|
||||
before do
|
||||
|
@ -11,26 +11,26 @@ RSpec.describe Jobs::EnqueueReminders do
|
|||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
it 'does not enqueue reminders when there are no assigned tasks' do
|
||||
describe "#execute" do
|
||||
it "does not enqueue reminders when there are no assigned tasks" do
|
||||
assert_reminders_enqueued(0)
|
||||
end
|
||||
|
||||
it 'does not enqueue reminders when no groups are allowed to assign' do
|
||||
SiteSetting.assign_allowed_on_groups = ''
|
||||
it "does not enqueue reminders when no groups are allowed to assign" do
|
||||
SiteSetting.assign_allowed_on_groups = ""
|
||||
|
||||
assign_multiple_tasks_to(user)
|
||||
|
||||
assert_reminders_enqueued(0)
|
||||
end
|
||||
|
||||
it 'enqueues a reminder when the user has more than one task' do
|
||||
it "enqueues a reminder when the user has more than one task" do
|
||||
assign_multiple_tasks_to(user)
|
||||
|
||||
assert_reminders_enqueued(1)
|
||||
end
|
||||
|
||||
it 'does not enqueue a reminder when the user only has one task' do
|
||||
it "does not enqueue a reminder when the user only has one task" do
|
||||
assign_one_task_to(user)
|
||||
|
||||
assert_reminders_enqueued(0)
|
||||
|
@ -43,31 +43,32 @@ RSpec.describe Jobs::EnqueueReminders do
|
|||
assert_reminders_enqueued(0)
|
||||
end
|
||||
|
||||
it 'enqueues a reminder if the user was reminded more than a month ago' do
|
||||
it "enqueues a reminder if the user was reminded more than a month ago" do
|
||||
user.upsert_custom_fields(PendingAssignsReminder::REMINDED_AT => 31.days.ago)
|
||||
assign_multiple_tasks_to(user)
|
||||
|
||||
assert_reminders_enqueued(1)
|
||||
end
|
||||
|
||||
it 'does not enqueue reminders if the remind frequency is set to never' do
|
||||
it "does not enqueue reminders if the remind frequency is set to never" do
|
||||
SiteSetting.remind_assigns_frequency = 0
|
||||
assign_multiple_tasks_to(user)
|
||||
|
||||
assert_reminders_enqueued(0)
|
||||
end
|
||||
|
||||
it 'does not enqueue reminders if the topic was just assigned to the user' do
|
||||
it "does not enqueue reminders if the topic was just assigned to the user" do
|
||||
just_assigned = DateTime.now
|
||||
assign_multiple_tasks_to(user, assigned_on: just_assigned)
|
||||
|
||||
assert_reminders_enqueued(0)
|
||||
end
|
||||
|
||||
it 'enqueues a reminder when the user overrides the global frequency' do
|
||||
it "enqueues a reminder when the user overrides the global frequency" do
|
||||
SiteSetting.remind_assigns_frequency = 0
|
||||
user.custom_fields.merge!(
|
||||
PendingAssignsReminder::REMINDERS_FREQUENCY => RemindAssignsFrequencySiteSettings::DAILY_MINUTES
|
||||
PendingAssignsReminder::REMINDERS_FREQUENCY =>
|
||||
RemindAssignsFrequencySiteSettings::DAILY_MINUTES,
|
||||
)
|
||||
user.save_custom_fields
|
||||
|
||||
|
@ -91,9 +92,7 @@ RSpec.describe Jobs::EnqueueReminders do
|
|||
end
|
||||
|
||||
def assign_one_task_to(user, assigned_on: 3.months.ago, post: Fabricate(:post))
|
||||
freeze_time(assigned_on) do
|
||||
Assigner.new(post.topic, user).assign(user)
|
||||
end
|
||||
freeze_time(assigned_on) { Assigner.new(post.topic, user).assign(user) }
|
||||
end
|
||||
|
||||
def assign_multiple_tasks_to(user, assigned_on: 3.months.ago)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Assigner do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
let(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
let(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
let(:pm_post) { Fabricate(:private_message_post) }
|
||||
let(:pm) { pm_post.topic }
|
||||
|
||||
|
@ -21,27 +21,23 @@ RSpec.describe Assigner do
|
|||
let(:assigner_self) { described_class.new(topic, moderator) }
|
||||
|
||||
it "can assign and unassign correctly" do
|
||||
expect_enqueued_with(job: :assign_notification) do
|
||||
assigner.assign(moderator)
|
||||
end
|
||||
expect_enqueued_with(job: :assign_notification) { assigner.assign(moderator) }
|
||||
|
||||
expect(TopicQuery.new(
|
||||
moderator, assigned: moderator.username
|
||||
).list_latest.topics).to eq([topic])
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq(
|
||||
[topic],
|
||||
)
|
||||
|
||||
expect(TopicUser.find_by(user: moderator).notification_level)
|
||||
.to eq(TopicUser.notification_levels[:watching])
|
||||
expect(TopicUser.find_by(user: moderator).notification_level).to eq(
|
||||
TopicUser.notification_levels[:watching],
|
||||
)
|
||||
|
||||
expect_enqueued_with(job: :unassign_notification) do
|
||||
assigner.unassign
|
||||
end
|
||||
expect_enqueued_with(job: :unassign_notification) { assigner.unassign }
|
||||
|
||||
expect(TopicQuery.new(
|
||||
moderator, assigned: moderator.username
|
||||
).list_latest.topics).to eq([])
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq([])
|
||||
|
||||
expect(TopicUser.find_by(user: moderator).notification_level)
|
||||
.to eq(TopicUser.notification_levels[:tracking])
|
||||
expect(TopicUser.find_by(user: moderator).notification_level).to eq(
|
||||
TopicUser.notification_levels[:tracking],
|
||||
)
|
||||
end
|
||||
|
||||
it "can assign with note" do
|
||||
|
@ -51,63 +47,76 @@ RSpec.describe Assigner do
|
|||
end
|
||||
|
||||
it "assign with note adds moderator post with note" do
|
||||
expect { assigner.assign(moderator, note: "tomtom best mom") }.to change { topic.posts.count }.by(1)
|
||||
expect { assigner.assign(moderator, note: "tomtom best mom") }.to change {
|
||||
topic.posts.count
|
||||
}.by(1)
|
||||
expect(topic.posts.last.raw).to eq "tomtom best mom"
|
||||
end
|
||||
|
||||
it "publishes topic assignment after assign and unassign" do
|
||||
messages = MessageBus.track_publish('/staff/topic-assignment') do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "tomtom best mom")
|
||||
assigner.unassign
|
||||
end
|
||||
messages =
|
||||
MessageBus.track_publish("/staff/topic-assignment") do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "tomtom best mom")
|
||||
assigner.unassign
|
||||
end
|
||||
|
||||
expect(messages[0].channel).to eq "/staff/topic-assignment"
|
||||
expect(messages[0].data).to include({
|
||||
type: "assigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assigned_to: BasicUserSerializer.new(moderator, scope: Guardian.new, root: false).as_json,
|
||||
assignment_note: "tomtom best mom"
|
||||
})
|
||||
|
||||
expect(messages[1].channel).to eq "/staff/topic-assignment"
|
||||
expect(messages[1].data).to include({
|
||||
type: "unassigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assignment_note: nil
|
||||
})
|
||||
end
|
||||
|
||||
it 'does not update notification level if already watching' do
|
||||
TopicUser.change(moderator.id, topic.id,
|
||||
notification_level: TopicUser.notification_levels[:watching]
|
||||
expect(messages[0].data).to include(
|
||||
{
|
||||
type: "assigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assigned_to: BasicUserSerializer.new(moderator, scope: Guardian.new, root: false).as_json,
|
||||
assignment_note: "tomtom best mom",
|
||||
},
|
||||
)
|
||||
|
||||
expect do
|
||||
assigner_self.assign(moderator)
|
||||
end.to_not change { TopicUser.last.notifications_reason_id }
|
||||
expect(messages[1].channel).to eq "/staff/topic-assignment"
|
||||
expect(messages[1].data).to include(
|
||||
{
|
||||
type: "unassigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assignment_note: nil,
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not update notification level if it is not set by the plugin' do
|
||||
it "does not update notification level if already watching" do
|
||||
TopicUser.change(
|
||||
moderator.id,
|
||||
topic.id,
|
||||
notification_level: TopicUser.notification_levels[:watching],
|
||||
)
|
||||
|
||||
expect do assigner_self.assign(moderator) end.to_not change {
|
||||
TopicUser.last.notifications_reason_id
|
||||
}
|
||||
end
|
||||
|
||||
it "does not update notification level if it is not set by the plugin" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
expect(TopicUser.find_by(user: moderator).notification_level)
|
||||
.to eq(TopicUser.notification_levels[:watching])
|
||||
expect(TopicUser.find_by(user: moderator).notification_level).to eq(
|
||||
TopicUser.notification_levels[:watching],
|
||||
)
|
||||
|
||||
TopicUser.change(moderator.id, topic.id,
|
||||
notification_level: TopicUser.notification_levels[:muted]
|
||||
TopicUser.change(
|
||||
moderator.id,
|
||||
topic.id,
|
||||
notification_level: TopicUser.notification_levels[:muted],
|
||||
)
|
||||
|
||||
assigner.unassign
|
||||
|
||||
expect(TopicUser.find_by(user: moderator, topic: topic).notification_level)
|
||||
.to eq(TopicUser.notification_levels[:muted])
|
||||
expect(TopicUser.find_by(user: moderator, topic: topic).notification_level).to eq(
|
||||
TopicUser.notification_levels[:muted],
|
||||
)
|
||||
end
|
||||
|
||||
context "when assigns_by_staff_mention is set to true" do
|
||||
|
@ -206,7 +215,7 @@ RSpec.describe Assigner do
|
|||
expect(second_assign[:success]).to eq(true)
|
||||
end
|
||||
|
||||
it 'fails to assign when the assigned user and note is the same' do
|
||||
it "fails to assign when the assigned user and note is the same" do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "note me down")
|
||||
|
||||
|
@ -216,7 +225,7 @@ RSpec.describe Assigner do
|
|||
expect(assign[:reason]).to eq(:already_assigned)
|
||||
end
|
||||
|
||||
it 'allows assign when the assigned user is same but note is different' do
|
||||
it "allows assign when the assigned user is same but note is different" do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "note me down")
|
||||
|
||||
|
@ -225,21 +234,21 @@ RSpec.describe Assigner do
|
|||
expect(assign[:success]).to eq(true)
|
||||
end
|
||||
|
||||
it 'fails to assign when the assigned user cannot view the pm' do
|
||||
it "fails to assign when the assigned user cannot view the pm" do
|
||||
assign = described_class.new(pm, moderator_2).assign(moderator)
|
||||
|
||||
expect(assign[:success]).to eq(false)
|
||||
expect(assign[:reason]).to eq(:forbidden_assignee_not_pm_participant)
|
||||
end
|
||||
|
||||
it 'fails to assign when the assigned admin cannot view the pm' do
|
||||
it "fails to assign when the assigned admin cannot view the pm" do
|
||||
assign = described_class.new(pm, moderator_2).assign(admin)
|
||||
|
||||
expect(assign[:success]).to eq(false)
|
||||
expect(assign[:reason]).to eq(:forbidden_assignee_not_pm_participant)
|
||||
end
|
||||
|
||||
it 'fails to assign when not all group members has access to pm' do
|
||||
it "fails to assign when not all group members has access to pm" do
|
||||
assign = described_class.new(pm, moderator_2).assign(moderator.groups.first)
|
||||
|
||||
expect(assign[:success]).to eq(false)
|
||||
|
@ -252,14 +261,14 @@ RSpec.describe Assigner do
|
|||
expect(assign[:reason]).to eq(:forbidden_group_assignee_not_pm_participant)
|
||||
end
|
||||
|
||||
it 'fails to assign when the assigned user cannot view the topic' do
|
||||
it "fails to assign when the assigned user cannot view the topic" do
|
||||
assign = described_class.new(secure_topic, moderator_2).assign(moderator)
|
||||
|
||||
expect(assign[:success]).to eq(false)
|
||||
expect(assign[:reason]).to eq(:forbidden_assignee_cant_see_topic)
|
||||
end
|
||||
|
||||
it 'fails to assign when the not all group members can view the topic' do
|
||||
it "fails to assign when the not all group members can view the topic" do
|
||||
assign = described_class.new(secure_topic, moderator_2).assign(moderator.groups.first)
|
||||
|
||||
expect(assign[:success]).to eq(false)
|
||||
|
@ -283,7 +292,7 @@ RSpec.describe Assigner do
|
|||
expect(assign[:success]).to eq(true)
|
||||
end
|
||||
|
||||
it 'triggers error for incorrect type' do
|
||||
it "triggers error for incorrect type" do
|
||||
expect do
|
||||
described_class.new(secure_category, moderator).assign(moderator)
|
||||
end.to raise_error(Discourse::InvalidAccess)
|
||||
|
@ -293,9 +302,9 @@ RSpec.describe Assigner do
|
|||
it "does not recreate assignment if no assignee change" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
expect do
|
||||
assigner.assign(moderator, note: "new notes!")
|
||||
end.to_not change { Assignment.last.id }
|
||||
expect do assigner.assign(moderator, note: "new notes!") end.to_not change {
|
||||
Assignment.last.id
|
||||
}
|
||||
end
|
||||
|
||||
it "updates notes" do
|
||||
|
@ -317,21 +326,25 @@ RSpec.describe Assigner do
|
|||
it "publishes topic assignment with note" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
messages = MessageBus.track_publish('/staff/topic-assignment') do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "new notes!")
|
||||
end
|
||||
messages =
|
||||
MessageBus.track_publish("/staff/topic-assignment") do
|
||||
assigner = described_class.new(topic, moderator_2)
|
||||
assigner.assign(moderator, note: "new notes!")
|
||||
end
|
||||
|
||||
expect(messages[0].channel).to eq "/staff/topic-assignment"
|
||||
expect(messages[0].data).to include({
|
||||
type: "assigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assigned_to: BasicUserSerializer.new(moderator, scope: Guardian.new, root: false).as_json,
|
||||
assignment_note: "new notes!"
|
||||
})
|
||||
expect(messages[0].data).to include(
|
||||
{
|
||||
type: "assigned",
|
||||
topic_id: topic.id,
|
||||
post_id: false,
|
||||
post_number: false,
|
||||
assigned_type: "User",
|
||||
assigned_to:
|
||||
BasicUserSerializer.new(moderator, scope: Guardian.new, root: false).as_json,
|
||||
assignment_note: "new notes!",
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
it "adds a note_change small action post" do
|
||||
|
@ -348,7 +361,9 @@ RSpec.describe Assigner do
|
|||
context "assign_self_regex" do
|
||||
fab!(:me) { Fabricate(:admin) }
|
||||
fab!(:op) { Fabricate(:post) }
|
||||
fab!(:reply) { Fabricate(:post, topic: op.topic, user: me, raw: "Will fix. Added to my list ;)") }
|
||||
fab!(:reply) do
|
||||
Fabricate(:post, topic: op.topic, user: me, raw: "Will fix. Added to my list ;)")
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.assigns_by_staff_mention = true
|
||||
|
@ -388,7 +403,14 @@ RSpec.describe Assigner do
|
|||
fab!(:me) { Fabricate(:admin) }
|
||||
fab!(:other) { Fabricate(:admin) }
|
||||
fab!(:op) { Fabricate(:post) }
|
||||
fab!(:reply) { Fabricate(:post, topic: op.topic, user: me, raw: "can you add this to your list, @#{other.username}") }
|
||||
fab!(:reply) do
|
||||
Fabricate(
|
||||
:post,
|
||||
topic: op.topic,
|
||||
user: me,
|
||||
raw: "can you add this to your list, @#{other.username}",
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.assigns_by_staff_mention = true
|
||||
|
@ -407,7 +429,7 @@ RSpec.describe Assigner do
|
|||
let(:topic) { post.topic }
|
||||
let(:moderator) { Fabricate(:moderator, groups: [assign_allowed_group]) }
|
||||
|
||||
context 'topic' do
|
||||
context "topic" do
|
||||
let(:assigner) { described_class.new(topic, moderator) }
|
||||
|
||||
before do
|
||||
|
@ -417,26 +439,34 @@ RSpec.describe Assigner do
|
|||
|
||||
it "unassigns on topic closed" do
|
||||
topic.update_status("closed", true, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_blank
|
||||
expect(
|
||||
TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics,
|
||||
).to be_blank
|
||||
end
|
||||
|
||||
it "unassigns on topic autoclosed" do
|
||||
topic.update_status("autoclosed", true, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_blank
|
||||
expect(
|
||||
TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics,
|
||||
).to be_blank
|
||||
end
|
||||
|
||||
it "does not unassign on topic open" do
|
||||
topic.update_status("closed", false, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq([topic])
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq(
|
||||
[topic],
|
||||
)
|
||||
end
|
||||
|
||||
it "does not unassign on automatic topic open" do
|
||||
topic.update_status("autoclosed", false, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq([topic])
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq(
|
||||
[topic],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'post' do
|
||||
context "post" do
|
||||
let(:post_2) { Fabricate(:post, topic: topic) }
|
||||
let(:assigner) { described_class.new(post_2, moderator) }
|
||||
|
||||
|
@ -447,7 +477,7 @@ RSpec.describe Assigner do
|
|||
assigner.assign(moderator)
|
||||
end
|
||||
|
||||
it 'deactivates post assignments when topic is closed' do
|
||||
it "deactivates post assignments when topic is closed" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
expect(post_2.assignment.active).to be true
|
||||
|
@ -456,7 +486,7 @@ RSpec.describe Assigner do
|
|||
expect(post_2.assignment.reload.active).to be false
|
||||
end
|
||||
|
||||
it 'deactivates post assignments when post is deleted and activate when recovered' do
|
||||
it "deactivates post assignments when post is deleted and activate when recovered" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
expect(post_2.assignment.active).to be true
|
||||
|
@ -468,7 +498,7 @@ RSpec.describe Assigner do
|
|||
expect(post_2.assignment.reload.active).to be true
|
||||
end
|
||||
|
||||
it 'deletes post small action for deleted post' do
|
||||
it "deletes post small action for deleted post" do
|
||||
assigner.assign(moderator)
|
||||
small_action_post = PostCustomField.where(name: "action_code_post_id").first.post
|
||||
|
||||
|
@ -483,7 +513,7 @@ RSpec.describe Assigner do
|
|||
let(:topic) { post.topic }
|
||||
let(:moderator) { Fabricate(:moderator, groups: [assign_allowed_group]) }
|
||||
|
||||
context 'topic' do
|
||||
context "topic" do
|
||||
let(:assigner) { described_class.new(topic, moderator) }
|
||||
|
||||
before do
|
||||
|
@ -494,14 +524,18 @@ RSpec.describe Assigner do
|
|||
|
||||
it "reassigns on topic open" do
|
||||
topic.update_status("closed", true, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to be_blank
|
||||
expect(
|
||||
TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics,
|
||||
).to be_blank
|
||||
|
||||
topic.update_status("closed", false, moderator)
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq([topic])
|
||||
expect(TopicQuery.new(moderator, assigned: moderator.username).list_latest.topics).to eq(
|
||||
[topic],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'post' do
|
||||
context "post" do
|
||||
let(:post_2) { Fabricate(:post, topic: topic) }
|
||||
let(:assigner) { described_class.new(post_2, moderator) }
|
||||
|
||||
|
@ -512,7 +546,7 @@ RSpec.describe Assigner do
|
|||
assigner.assign(moderator)
|
||||
end
|
||||
|
||||
it 'reassigns post on topic open' do
|
||||
it "reassigns post on topic open" do
|
||||
assigner.assign(moderator)
|
||||
|
||||
expect(post_2.assignment.active).to be true
|
||||
|
@ -535,36 +569,41 @@ RSpec.describe Assigner do
|
|||
it "send an email if set to 'always'" do
|
||||
SiteSetting.assign_mailer = AssignMailer.levels[:always]
|
||||
|
||||
expect { described_class.new(topic, moderator).assign(moderator) }
|
||||
.to change { ActionMailer::Base.deliveries.size }.by(1)
|
||||
expect { described_class.new(topic, moderator).assign(moderator) }.to change {
|
||||
ActionMailer::Base.deliveries.size
|
||||
}.by(1)
|
||||
end
|
||||
|
||||
it "doesn't send an email if assignee is a group" do
|
||||
SiteSetting.assign_mailer = AssignMailer.levels[:always]
|
||||
|
||||
expect { described_class.new(topic, moderator).assign(assign_allowed_group) }
|
||||
.to change { ActionMailer::Base.deliveries.size }.by(0)
|
||||
expect { described_class.new(topic, moderator).assign(assign_allowed_group) }.to change {
|
||||
ActionMailer::Base.deliveries.size
|
||||
}.by(0)
|
||||
end
|
||||
|
||||
it "doesn't send an email if the assigner and assignee are not different" do
|
||||
SiteSetting.assign_mailer = AssignMailer.levels[:different_users]
|
||||
|
||||
expect { described_class.new(topic, moderator).assign(moderator_2) }
|
||||
.to change { ActionMailer::Base.deliveries.size }.by(1)
|
||||
expect { described_class.new(topic, moderator).assign(moderator_2) }.to change {
|
||||
ActionMailer::Base.deliveries.size
|
||||
}.by(1)
|
||||
end
|
||||
|
||||
it "doesn't send an email if the assigner and assignee are not different" do
|
||||
SiteSetting.assign_mailer = AssignMailer.levels[:different_users]
|
||||
|
||||
expect { described_class.new(topic, moderator).assign(moderator) }
|
||||
.to change { ActionMailer::Base.deliveries.size }.by(0)
|
||||
expect { described_class.new(topic, moderator).assign(moderator) }.to change {
|
||||
ActionMailer::Base.deliveries.size
|
||||
}.by(0)
|
||||
end
|
||||
|
||||
it "doesn't send an email" do
|
||||
SiteSetting.assign_mailer = AssignMailer.levels[:never]
|
||||
|
||||
expect { described_class.new(topic, moderator).assign(moderator_2) }
|
||||
.to change { ActionMailer::Base.deliveries.size }.by(0)
|
||||
expect { described_class.new(topic, moderator).assign(moderator_2) }.to change {
|
||||
ActionMailer::Base.deliveries.size
|
||||
}.by(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
def assert_reminder_not_created
|
||||
expect { subject.remind(user) }.to change { Post.count }.by(0)
|
||||
|
@ -12,21 +12,21 @@ RSpec.describe PendingAssignsReminder do
|
|||
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
it 'does not create a reminder if the user has 0 assigned topics' do
|
||||
it "does not create a reminder if the user has 0 assigned topics" do
|
||||
assert_reminder_not_created
|
||||
end
|
||||
|
||||
it 'does not create a reminder if the user only has one task' do
|
||||
it "does not create a reminder if the user only has one task" do
|
||||
post = Fabricate(:post)
|
||||
Assigner.new(post.topic, user).assign(user)
|
||||
|
||||
assert_reminder_not_created
|
||||
end
|
||||
|
||||
describe 'when the user has multiple tasks' do
|
||||
describe "when the user has multiple tasks" do
|
||||
let(:system) { Discourse.system_user }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user)
|
||||
|
@ -46,7 +46,7 @@ RSpec.describe PendingAssignsReminder do
|
|||
@post4.topic.update(category: secure_category)
|
||||
end
|
||||
|
||||
it 'creates a reminder for a particular user and sets the timestamp of the last reminder' do
|
||||
it "creates a reminder for a particular user and sets the timestamp of the last reminder" do
|
||||
freeze_time
|
||||
subject.remind(user)
|
||||
|
||||
|
@ -56,31 +56,29 @@ RSpec.describe PendingAssignsReminder do
|
|||
expect(topic.user).to eq(system)
|
||||
expect(topic.archetype).to eq(Archetype.private_message)
|
||||
|
||||
expect(topic.topic_allowed_users.pluck(:user_id)).to contain_exactly(
|
||||
system.id, user.id
|
||||
)
|
||||
expect(topic.topic_allowed_users.pluck(:user_id)).to contain_exactly(system.id, user.id)
|
||||
|
||||
expect(topic.title).to eq(I18n.t(
|
||||
'pending_assigns_reminder.title',
|
||||
pending_assignments: 3
|
||||
))
|
||||
expect(topic.title).to eq(I18n.t("pending_assigns_reminder.title", pending_assignments: 3))
|
||||
|
||||
expect(post.raw).to include(@post1.topic.fancy_title)
|
||||
expect(post.raw).to include(@post2.topic.fancy_title)
|
||||
expect(post.raw).to_not include(@post3.topic.fancy_title)
|
||||
expect(post.raw).to_not include(@post4.topic.fancy_title)
|
||||
|
||||
expect(
|
||||
user.reload.custom_fields[described_class::REMINDED_AT].to_datetime
|
||||
).to eq_time(DateTime.now)
|
||||
expect(user.reload.custom_fields[described_class::REMINDED_AT].to_datetime).to eq_time(
|
||||
DateTime.now,
|
||||
)
|
||||
end
|
||||
|
||||
it 'deletes previous reminders when creating a new one' do
|
||||
it "deletes previous reminders when creating a new one" do
|
||||
subject.remind(user)
|
||||
subject.remind(user)
|
||||
|
||||
reminders_count = Topic.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME }).count
|
||||
reminders_count =
|
||||
Topic
|
||||
.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME })
|
||||
.count
|
||||
|
||||
expect(reminders_count).to eq(1)
|
||||
end
|
||||
|
@ -96,8 +94,11 @@ RSpec.describe PendingAssignsReminder do
|
|||
|
||||
subject.remind(another_user)
|
||||
|
||||
reminders_count = Topic.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME }).count
|
||||
reminders_count =
|
||||
Topic
|
||||
.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME })
|
||||
.count
|
||||
|
||||
expect(reminders_count).to eq(2)
|
||||
end
|
||||
|
@ -107,8 +108,11 @@ RSpec.describe PendingAssignsReminder do
|
|||
Fabricate(:post, topic: Topic.last)
|
||||
subject.remind(user)
|
||||
|
||||
reminders_count = Topic.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME }).count
|
||||
reminders_count =
|
||||
Topic
|
||||
.joins(:_custom_fields)
|
||||
.where(topic_custom_fields: { name: described_class::CUSTOM_FIELD_NAME })
|
||||
.count
|
||||
|
||||
expect(reminders_count).to eq(2)
|
||||
end
|
||||
|
@ -124,10 +128,7 @@ RSpec.describe PendingAssignsReminder do
|
|||
post = Post.last
|
||||
topic = post.topic
|
||||
|
||||
expect(topic.title).to eq(I18n.t(
|
||||
'pending_assigns_reminder.title',
|
||||
pending_assignments: 4
|
||||
))
|
||||
expect(topic.title).to eq(I18n.t("pending_assigns_reminder.title", pending_assignments: 4))
|
||||
|
||||
@post5.topic.update_status("closed", true, Discourse.system_user)
|
||||
expect(@post5.topic.closed).to eq(true)
|
||||
|
@ -137,11 +138,7 @@ RSpec.describe PendingAssignsReminder do
|
|||
post = Post.last
|
||||
topic = post.topic
|
||||
|
||||
expect(topic.title).to eq(I18n.t(
|
||||
'pending_assigns_reminder.title',
|
||||
pending_assignments: 3
|
||||
))
|
||||
expect(topic.title).to eq(I18n.t("pending_assigns_reminder.title", pending_assignments: 3))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require 'random_assign_utils'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
require "random_assign_utils"
|
||||
|
||||
describe RandomAssignUtils do
|
||||
before do
|
||||
|
@ -12,33 +12,44 @@ describe RandomAssignUtils do
|
|||
Rails.logger = @fake_logger = FakeLogger.new
|
||||
end
|
||||
|
||||
after do
|
||||
Rails.logger = @orig_logger
|
||||
end
|
||||
after { Rails.logger = @orig_logger }
|
||||
|
||||
FakeAutomation = Struct.new(:id)
|
||||
|
||||
let(:post) { Fabricate(:post) }
|
||||
let!(:automation) { FakeAutomation.new(1) }
|
||||
|
||||
describe '.automation_script!' do
|
||||
context 'all users of group are on holidays' do
|
||||
describe ".automation_script!" do
|
||||
context "all users of group are on holidays" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
fab!(:group_1) { Fabricate(:group) }
|
||||
fab!(:user_1) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
group_1.add(user_1)
|
||||
UserCustomField.create!(name: 'on_holiday', value: 't', user_id: user_1.id)
|
||||
UserCustomField.create!(name: "on_holiday", value: "t", user_id: user_1.id)
|
||||
end
|
||||
|
||||
it 'creates post on the topic' do
|
||||
described_class.automation_script!({}, { 'assignees_group' => { 'value' => group_1.id }, 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
expect(topic_1.posts.first.raw).to match("Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.")
|
||||
it "creates post on the topic" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"assignees_group" => {
|
||||
"value" => group_1.id,
|
||||
},
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(topic_1.posts.first.raw).to match(
|
||||
"Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'all users of group have been assigned recently' do
|
||||
context "all users of group have been assigned recently" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
fab!(:group_1) { Fabricate(:group) }
|
||||
fab!(:user_1) { Fabricate(:user) }
|
||||
|
@ -48,127 +59,217 @@ describe RandomAssignUtils do
|
|||
group_1.add(user_1)
|
||||
end
|
||||
|
||||
it 'creates post on the topic' do
|
||||
described_class.automation_script!({}, { 'assignees_group' => { 'value' => group_1.id }, 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
expect(topic_1.posts.first.raw).to match("Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.")
|
||||
it "creates post on the topic" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"assignees_group" => {
|
||||
"value" => group_1.id,
|
||||
},
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(topic_1.posts.first.raw).to match(
|
||||
"Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'user can be assigned' do
|
||||
context "user can be assigned" do
|
||||
fab!(:group_1) { Fabricate(:group) }
|
||||
fab!(:user_1) { Fabricate(:user) }
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_allowed_on_groups = [group_1.id.to_s].join('|')
|
||||
SiteSetting.assign_allowed_on_groups = [group_1.id.to_s].join("|")
|
||||
group_1.add(user_1)
|
||||
end
|
||||
|
||||
context 'post_template is set' do
|
||||
it 'creates a post with the template and assign the user' do
|
||||
described_class.automation_script!({}, { 'post_template' => { 'value' => 'this is a post template' }, 'assignees_group' => { 'value' => group_1.id }, 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
expect(topic_1.posts.first.raw).to match('this is a post template')
|
||||
context "post_template is set" do
|
||||
it "creates a post with the template and assign the user" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"post_template" => {
|
||||
"value" => "this is a post template",
|
||||
},
|
||||
"assignees_group" => {
|
||||
"value" => group_1.id,
|
||||
},
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(topic_1.posts.first.raw).to match("this is a post template")
|
||||
end
|
||||
end
|
||||
|
||||
context 'post_template is not set' do
|
||||
context "post_template is not set" do
|
||||
fab!(:post_1) { Fabricate(:post, topic: topic_1) }
|
||||
|
||||
it 'assigns the user to the topic' do
|
||||
described_class.automation_script!({}, { 'assignees_group' => { 'value' => group_1.id }, 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
it "assigns the user to the topic" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"assignees_group" => {
|
||||
"value" => group_1.id,
|
||||
},
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(topic_1.assignment.assigned_to_id).to eq(user_1.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'all users in working hours' do
|
||||
context "all users in working hours" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
fab!(:group_1) { Fabricate(:group) }
|
||||
fab!(:user_1) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
freeze_time('2022-10-01 02:00')
|
||||
UserOption.find_by(user_id: user_1.id).update(timezone: 'Europe/Paris')
|
||||
freeze_time("2022-10-01 02:00")
|
||||
UserOption.find_by(user_id: user_1.id).update(timezone: "Europe/Paris")
|
||||
group_1.add(user_1)
|
||||
end
|
||||
|
||||
it 'creates post on the topic' do
|
||||
described_class.automation_script!({}, { 'in_working_hours' => { 'value' => true }, 'assignees_group' => { 'value' => group_1.id }, 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
expect(topic_1.posts.first.raw).to match("Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.")
|
||||
it "creates post on the topic" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"in_working_hours" => {
|
||||
"value" => true,
|
||||
},
|
||||
"assignees_group" => {
|
||||
"value" => group_1.id,
|
||||
},
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(topic_1.posts.first.raw).to match(
|
||||
"Attempted randomly assign a member of `@#{group_1.name}`, but no one was available.",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'assignees_group not provided' do
|
||||
context "assignees_group not provided" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
|
||||
it 'raises an error' do
|
||||
it "raises an error" do
|
||||
expect {
|
||||
described_class.automation_script!({}, { 'assigned_topic' => { 'value' => topic_1.id } }, automation)
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{ "assigned_topic" => { "value" => topic_1.id } },
|
||||
automation,
|
||||
)
|
||||
}.to raise_error(/`assignees_group` not provided/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'assignees_group not found' do
|
||||
context "assignees_group not found" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
|
||||
it 'raises an error' do
|
||||
it "raises an error" do
|
||||
expect {
|
||||
described_class.automation_script!({}, { 'assigned_topic' => { 'value' => topic_1.id }, 'assignees_group' => { 'value' => -1 } }, automation)
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
"assignees_group" => {
|
||||
"value" => -1,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
}.to raise_error(/Group\(-1\) not found/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'assigned_topic not provided' do
|
||||
it 'raises an error' do
|
||||
expect {
|
||||
described_class.automation_script!({}, {}, automation)
|
||||
}.to raise_error(/`assigned_topic` not provided/)
|
||||
context "assigned_topic not provided" do
|
||||
it "raises an error" do
|
||||
expect { described_class.automation_script!({}, {}, automation) }.to raise_error(
|
||||
/`assigned_topic` not provided/,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'assigned_topic is not found' do
|
||||
it 'raises an error' do
|
||||
context "assigned_topic is not found" do
|
||||
it "raises an error" do
|
||||
expect {
|
||||
described_class.automation_script!({}, { 'assigned_topic' => { 'value' => 1 } }, automation)
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{ "assigned_topic" => { "value" => 1 } },
|
||||
automation,
|
||||
)
|
||||
}.to raise_error(/Topic\(1\) not found/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'minimum_time_between_assignments is set' do
|
||||
context 'the topic has been assigned recently' do
|
||||
context "minimum_time_between_assignments is set" do
|
||||
context "the topic has been assigned recently" do
|
||||
fab!(:topic_1) { Fabricate(:topic) }
|
||||
|
||||
before do
|
||||
freeze_time
|
||||
TopicCustomField.create!(name: 'assigned_to_id', topic_id: topic_1.id, created_at: 20.hours.ago)
|
||||
TopicCustomField.create!(
|
||||
name: "assigned_to_id",
|
||||
topic_id: topic_1.id,
|
||||
created_at: 20.hours.ago,
|
||||
)
|
||||
end
|
||||
|
||||
it 'logs a warning' do
|
||||
described_class.automation_script!({}, { 'assigned_topic' => { 'value' => topic_1.id }, 'minimum_time_between_assignments' => { 'value' => 10 } }, automation)
|
||||
expect(Rails.logger.infos.first).to match(/Topic\(#{topic_1.id}\) has already been assigned recently/)
|
||||
it "logs a warning" do
|
||||
described_class.automation_script!(
|
||||
{},
|
||||
{
|
||||
"assigned_topic" => {
|
||||
"value" => topic_1.id,
|
||||
},
|
||||
"minimum_time_between_assignments" => {
|
||||
"value" => 10,
|
||||
},
|
||||
},
|
||||
automation,
|
||||
)
|
||||
expect(Rails.logger.infos.first).to match(
|
||||
/Topic\(#{topic_1.id}\) has already been assigned recently/,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.recently_assigned_users_ids' do
|
||||
context 'no one has been assigned' do
|
||||
it 'returns an empty array' do
|
||||
describe ".recently_assigned_users_ids" do
|
||||
context "no one has been assigned" do
|
||||
it "returns an empty array" do
|
||||
assignees_ids = described_class.recently_assigned_users_ids(post.topic_id, 2.months.ago)
|
||||
expect(assignees_ids).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context 'users have been assigned' do
|
||||
context "users have been assigned" do
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:assign_allowed_group) { Group.find_by(name: 'staff') }
|
||||
let(:assign_allowed_group) { Group.find_by(name: "staff") }
|
||||
let(:user_1) { Fabricate(:user, groups: [assign_allowed_group]) }
|
||||
let(:user_2) { Fabricate(:user, groups: [assign_allowed_group]) }
|
||||
let(:user_3) { Fabricate(:user, groups: [assign_allowed_group]) }
|
||||
let(:user_4) { Fabricate(:user, groups: [assign_allowed_group]) }
|
||||
let(:post_2) { Fabricate(:post, topic: post.topic) }
|
||||
|
||||
it 'returns the recently assigned user ids' do
|
||||
it "returns the recently assigned user ids" do
|
||||
freeze_time 1.months.ago do
|
||||
Assigner.new(post.topic, admin).assign(user_1)
|
||||
Assigner.new(post.topic, admin).assign(user_2)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'topic_view'
|
||||
require "topic_view"
|
||||
|
||||
describe TopicQuery do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
@ -13,17 +13,13 @@ describe TopicQuery do
|
|||
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
|
||||
describe '#list_group_topics_assigned' do
|
||||
describe "#list_group_topics_assigned" do
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
|
||||
[user, admin, other_admin].each do |user|
|
||||
group.add(user)
|
||||
end
|
||||
[user, admin, other_admin].each { |user| group.add(user) }
|
||||
|
||||
[user_pm, admin_pm, other_admin_pm].each do |topic|
|
||||
Fabricate(:post, topic: topic)
|
||||
end
|
||||
[user_pm, admin_pm, other_admin_pm].each { |topic| Fabricate(:post, topic: topic) }
|
||||
Fabricate(:topic_allowed_user, user: admin, topic: user_pm)
|
||||
|
||||
Assigner.new(user_pm, Discourse.system_user).assign(admin)
|
||||
|
@ -32,9 +28,17 @@ describe TopicQuery do
|
|||
end
|
||||
|
||||
it "includes PMs from all users" do
|
||||
expect(TopicQuery.new(user).list_group_topics_assigned(group).topics).to contain_exactly(user_pm)
|
||||
expect(TopicQuery.new(admin).list_group_topics_assigned(group).topics).to contain_exactly(user_pm, admin_pm, other_admin_pm)
|
||||
expect(TopicQuery.new(other_admin).list_group_topics_assigned(group).topics).to contain_exactly(user_pm, admin_pm, other_admin_pm)
|
||||
expect(TopicQuery.new(user).list_group_topics_assigned(group).topics).to contain_exactly(
|
||||
user_pm,
|
||||
)
|
||||
expect(TopicQuery.new(admin).list_group_topics_assigned(group).topics).to contain_exactly(
|
||||
user_pm,
|
||||
admin_pm,
|
||||
other_admin_pm,
|
||||
)
|
||||
expect(
|
||||
TopicQuery.new(other_admin).list_group_topics_assigned(group).topics,
|
||||
).to contain_exactly(user_pm, admin_pm, other_admin_pm)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
RSpec.describe Group do
|
||||
let(:group) { Fabricate(:group) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
context 'Tracking changes that could affect the allow assign on groups site setting' do
|
||||
|
||||
let(:removed_group_setting) { '3|4' }
|
||||
context "Tracking changes that could affect the allow assign on groups site setting" do
|
||||
let(:removed_group_setting) { "3|4" }
|
||||
let(:group_attribute) { group.id }
|
||||
|
||||
it 'removes the group from the setting when the group gets destroyed' do
|
||||
it "removes the group from the setting when the group gets destroyed" do
|
||||
SiteSetting.assign_allowed_on_groups = "#{group_attribute}|#{removed_group_setting}"
|
||||
|
||||
group.destroy!
|
||||
|
@ -23,7 +20,7 @@ RSpec.describe Group do
|
|||
expect(SiteSetting.assign_allowed_on_groups).to eq removed_group_setting
|
||||
end
|
||||
|
||||
it 'removes the group from the setting when this is the last one on the list' do
|
||||
it "removes the group from the setting when this is the last one on the list" do
|
||||
SiteSetting.assign_allowed_on_groups = "#{removed_group_setting}|#{group_attribute}"
|
||||
|
||||
group.destroy!
|
||||
|
@ -31,7 +28,7 @@ RSpec.describe Group do
|
|||
expect(SiteSetting.assign_allowed_on_groups).to eq removed_group_setting
|
||||
end
|
||||
|
||||
it 'removes the group from the list when it is on the middle of the list' do
|
||||
it "removes the group from the list when it is on the middle of the list" do
|
||||
allowed_groups = "3|#{group_attribute}|4"
|
||||
SiteSetting.assign_allowed_on_groups = allowed_groups
|
||||
|
||||
|
@ -41,13 +38,13 @@ RSpec.describe Group do
|
|||
end
|
||||
end
|
||||
|
||||
context 'includes can_show_assigned_tab? method' do
|
||||
context "includes can_show_assigned_tab? method" do
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:user1) { Fabricate(:user) }
|
||||
let(:user2) { Fabricate(:user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
add_to_assign_allowed_group(user)
|
||||
|
@ -55,7 +52,7 @@ RSpec.describe Group do
|
|||
add_to_assign_allowed_group(admin)
|
||||
end
|
||||
|
||||
it 'gives false in can_show_assigned_tab? when all users are not in assigned_allowed_group' do
|
||||
it "gives false in can_show_assigned_tab? when all users are not in assigned_allowed_group" do
|
||||
group.add(user)
|
||||
group.add(user1)
|
||||
group.add(user2)
|
||||
|
@ -63,7 +60,7 @@ RSpec.describe Group do
|
|||
expect(group.can_show_assigned_tab?).to eq(false)
|
||||
end
|
||||
|
||||
it 'gives true in can_show_assigned_tab? when all users are in assigned_allowed_group' do
|
||||
it "gives true in can_show_assigned_tab? when all users are in assigned_allowed_group" do
|
||||
group.add(user)
|
||||
group.add(user1)
|
||||
|
||||
|
|
|
@ -8,14 +8,24 @@ describe Reviewable do
|
|||
fab!(:reviewable1) { Fabricate(:reviewable_flagged_post, target: post1) }
|
||||
fab!(:reviewable2) { Fabricate(:reviewable_flagged_post, target: post2) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
it "can filter by assigned_to" do
|
||||
Assignment.create!(target: post1, topic_id: post1.topic.id, assigned_by_user: user, assigned_to: user)
|
||||
Assignment.create!(target: post2, topic_id: post2.topic.id, assigned_by_user: user, assigned_to: admin)
|
||||
Assignment.create!(
|
||||
target: post1,
|
||||
topic_id: post1.topic.id,
|
||||
assigned_by_user: user,
|
||||
assigned_to: user,
|
||||
)
|
||||
Assignment.create!(
|
||||
target: post2,
|
||||
topic_id: post2.topic.id,
|
||||
assigned_by_user: user,
|
||||
assigned_to: admin,
|
||||
)
|
||||
|
||||
expect(Reviewable.list_for(admin, additional_filters: { assigned_to: user.username })).to eq([reviewable1])
|
||||
expect(Reviewable.list_for(admin, additional_filters: { assigned_to: user.username })).to eq(
|
||||
[reviewable1],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,19 +8,29 @@ describe Topic do
|
|||
let(:group) { Fabricate(:group) }
|
||||
let(:topic) { Fabricate(:topic) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
end
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
describe "#assigned_to" do
|
||||
it "correctly points to a user" do
|
||||
Assignment.create!(target_id: topic.id, target_type: "Topic", topic_id: topic.id, assigned_by_user: user1, assigned_to: user2)
|
||||
Assignment.create!(
|
||||
target_id: topic.id,
|
||||
target_type: "Topic",
|
||||
topic_id: topic.id,
|
||||
assigned_by_user: user1,
|
||||
assigned_to: user2,
|
||||
)
|
||||
|
||||
expect(topic.reload.assigned_to).to eq(user2)
|
||||
end
|
||||
|
||||
it "correctly points to a group" do
|
||||
Assignment.create!(target_id: topic.id, target_type: "Topic", topic_id: topic.id, assigned_by_user: user1, assigned_to: group)
|
||||
Assignment.create!(
|
||||
target_id: topic.id,
|
||||
target_type: "Topic",
|
||||
topic_id: topic.id,
|
||||
assigned_by_user: user1,
|
||||
assigned_to: group,
|
||||
)
|
||||
|
||||
expect(topic.reload.assigned_to).to eq(group)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe UserCustomField do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
@ -8,12 +8,12 @@ RSpec.describe UserCustomField do
|
|||
let(:field_name) { PendingAssignsReminder::REMINDERS_FREQUENCY }
|
||||
let(:new_field) { UserCustomField.new(name: field_name, user_id: 1) }
|
||||
|
||||
it 'coerces the value to be an integer' do
|
||||
new_field.value = 'DROP TABLE USERS;'
|
||||
it "coerces the value to be an integer" do
|
||||
new_field.value = "DROP TABLE USERS;"
|
||||
|
||||
new_field.save!
|
||||
saved_field = new_field.reload
|
||||
|
||||
expect(saved_field.value).to eq('0')
|
||||
expect(saved_field.value).to eq("0")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
describe 'plugin' do
|
||||
describe "plugin" do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
describe 'events' do
|
||||
describe 'on user_removed_from_group' do
|
||||
describe "events" do
|
||||
describe "on user_removed_from_group" do
|
||||
before do
|
||||
@topic = Fabricate(:post).topic
|
||||
@user = Fabricate(:user)
|
||||
|
@ -14,7 +14,7 @@ describe 'plugin' do
|
|||
@group_a.add(@user)
|
||||
end
|
||||
|
||||
it 'unassigns the user' do
|
||||
it "unassigns the user" do
|
||||
SiteSetting.assign_allowed_on_groups = @group_a.id.to_s
|
||||
|
||||
Assigner.new(@topic, Discourse.system_user).assign(@user)
|
||||
|
@ -26,7 +26,7 @@ describe 'plugin' do
|
|||
it "doesn't unassign the user if it still has access through another group" do
|
||||
@group_b = Fabricate(:group)
|
||||
@group_b.add(@user)
|
||||
SiteSetting.assign_allowed_on_groups = [@group_a.id.to_s, @group_b.id.to_s].join('|')
|
||||
SiteSetting.assign_allowed_on_groups = [@group_a.id.to_s, @group_b.id.to_s].join("|")
|
||||
|
||||
Assigner.new(@topic, Discourse.system_user).assign(@user)
|
||||
@group_a.remove(@user)
|
||||
|
|
|
@ -1,45 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
RSpec.describe DiscourseAssign::AssignController do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
||||
fab!(:default_allowed_group) { Group.find_by(name: 'staff') }
|
||||
let(:user) { Fabricate(:admin, groups: [default_allowed_group], name: 'Robin Ward', username: 'eviltrout') }
|
||||
fab!(:default_allowed_group) { Group.find_by(name: "staff") }
|
||||
let(:user) do
|
||||
Fabricate(:admin, groups: [default_allowed_group], name: "Robin Ward", username: "eviltrout")
|
||||
end
|
||||
fab!(:post) { Fabricate(:post) }
|
||||
fab!(:user2) { Fabricate(:active_user, name: 'David Tylor', username: 'david', groups: [default_allowed_group]) }
|
||||
fab!(:user2) do
|
||||
Fabricate(:active_user, name: "David Tylor", username: "david", groups: [default_allowed_group])
|
||||
end
|
||||
let(:nonadmin) { Fabricate(:user, groups: [default_allowed_group]) }
|
||||
fab!(:normal_user) { Fabricate(:user) }
|
||||
fab!(:normal_admin) { Fabricate(:admin) }
|
||||
|
||||
context 'only allow users from allowed groups' do
|
||||
context "only allow users from allowed groups" do
|
||||
before { sign_in(user2) }
|
||||
|
||||
it 'filters requests where current_user is not member of an allowed group' do
|
||||
SiteSetting.assign_allowed_on_groups = ''
|
||||
it "filters requests where current_user is not member of an allowed group" do
|
||||
SiteSetting.assign_allowed_on_groups = ""
|
||||
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', username: user2.username
|
||||
}
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: user2.username,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it 'filters requests where assigne group is not allowed' do
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', group_name: default_allowed_group.name
|
||||
}
|
||||
it "filters requests where assigne group is not allowed" do
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
group_name: default_allowed_group.name,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
end
|
||||
|
||||
describe '#suggestions' do
|
||||
describe "#suggestions" do
|
||||
before { sign_in(user) }
|
||||
|
||||
it 'includes users in allowed groups' do
|
||||
allowed_group = Group.find_by(name: 'everyone')
|
||||
it "includes users in allowed groups" do
|
||||
allowed_group = Group.find_by(name: "everyone")
|
||||
allowed_group.add(user2)
|
||||
|
||||
defaults = "#{default_allowed_group.id}|#{allowed_group.id}"
|
||||
|
@ -47,25 +57,25 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
SiteSetting.assign_allowed_on_groups = defaults
|
||||
Assigner.new(post.topic, user).assign(user2)
|
||||
|
||||
get '/assign/suggestions.json'
|
||||
suggestions = JSON.parse(response.body)['suggestions'].map { |u| u['username'] }
|
||||
get "/assign/suggestions.json"
|
||||
suggestions = JSON.parse(response.body)["suggestions"].map { |u| u["username"] }
|
||||
|
||||
expect(suggestions).to contain_exactly(user2.username, user.username)
|
||||
end
|
||||
|
||||
it 'does not include users from disallowed groups' do
|
||||
allowed_group = Group.find_by(name: 'everyone')
|
||||
it "does not include users from disallowed groups" do
|
||||
allowed_group = Group.find_by(name: "everyone")
|
||||
allowed_group.add(user2)
|
||||
SiteSetting.assign_allowed_on_groups = default_allowed_group.id.to_s
|
||||
Assigner.new(post.topic, user).assign(user2)
|
||||
|
||||
get '/assign/suggestions.json'
|
||||
suggestions = JSON.parse(response.body)['suggestions'].map { |u| u['username'] }.sort
|
||||
get "/assign/suggestions.json"
|
||||
suggestions = JSON.parse(response.body)["suggestions"].map { |u| u["username"] }.sort
|
||||
|
||||
expect(suggestions).to eq(['david', 'eviltrout'])
|
||||
expect(suggestions).to eq(%w[david eviltrout])
|
||||
end
|
||||
|
||||
it 'does include only visible assign_allowed_on_groups' do
|
||||
it "does include only visible assign_allowed_on_groups" do
|
||||
sign_in(nonadmin) # Need to use nonadmin to test. Admins can see all groups
|
||||
|
||||
visible_group = Fabricate(:group, visibility_level: Group.visibility_levels[:members])
|
||||
|
@ -74,8 +84,8 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
|
||||
SiteSetting.assign_allowed_on_groups = "#{visible_group.id}|#{invisible_group.id}"
|
||||
|
||||
get '/assign/suggestions.json'
|
||||
assign_allowed_on_groups = JSON.parse(response.body)['assign_allowed_on_groups']
|
||||
get "/assign/suggestions.json"
|
||||
assign_allowed_on_groups = JSON.parse(response.body)["assign_allowed_on_groups"]
|
||||
|
||||
expect(assign_allowed_on_groups).to contain_exactly(visible_group.name)
|
||||
end
|
||||
|
@ -88,68 +98,86 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'excludes other users from the suggestions when they already reached the max assigns limit' do
|
||||
it "excludes other users from the suggestions when they already reached the max assigns limit" do
|
||||
another_admin = Fabricate(:admin, groups: [default_allowed_group])
|
||||
Assigner.new(post.topic, user).assign(another_admin)
|
||||
|
||||
get '/assign/suggestions.json'
|
||||
suggestions = JSON.parse(response.body)['suggestions'].map { |u| u['username'] }
|
||||
get "/assign/suggestions.json"
|
||||
suggestions = JSON.parse(response.body)["suggestions"].map { |u| u["username"] }
|
||||
|
||||
expect(suggestions).to contain_exactly(user.username)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assign' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
describe "#assign" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
add_to_assign_allowed_group(user2)
|
||||
end
|
||||
|
||||
it 'assigns topic to a user' do
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', username: user2.username
|
||||
}
|
||||
it "assigns topic to a user" do
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: user2.username,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(post.topic.reload.assignment.assigned_to_id).to eq(user2.id)
|
||||
end
|
||||
|
||||
it 'assigns topic with note to a user' do
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', username: user2.username, note: "do dis pls"
|
||||
}
|
||||
it "assigns topic with note to a user" do
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: user2.username,
|
||||
note: "do dis pls",
|
||||
}
|
||||
|
||||
expect(post.topic.reload.assignment.note).to eq("do dis pls")
|
||||
end
|
||||
|
||||
it 'assigns topic to a group' do
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', group_name: assign_allowed_group.name
|
||||
}
|
||||
it "assigns topic to a group" do
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
group_name: assign_allowed_group.name,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(post.topic.reload.assignment.assigned_to).to eq(assign_allowed_group)
|
||||
end
|
||||
|
||||
it 'fails to assign topic to the user if its already assigned to the same user' do
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', username: user2.username
|
||||
}
|
||||
it "fails to assign topic to the user if its already assigned to the same user" do
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: user2.username,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(post.topic.reload.assignment.assigned_to_id).to eq(user2.id)
|
||||
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: post.topic_id, target_type: 'Topic', username: user2.username
|
||||
}
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: user2.username,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
expect(JSON.parse(response.body)['error']).to eq(I18n.t('discourse_assign.already_assigned', username: user2.username))
|
||||
expect(JSON.parse(response.body)["error"]).to eq(
|
||||
I18n.t("discourse_assign.already_assigned", username: user2.username),
|
||||
)
|
||||
end
|
||||
|
||||
it 'fails to assign topic to the user if they already reached the max assigns limit' do
|
||||
it "fails to assign topic to the user if they already reached the max assigns limit" do
|
||||
another_user = Fabricate(:user)
|
||||
add_to_assign_allowed_group(another_user)
|
||||
another_post = Fabricate(:post)
|
||||
|
@ -157,45 +185,64 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
SiteSetting.max_assigned_topics = max_assigns
|
||||
Assigner.new(post.topic, user).assign(another_user)
|
||||
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: another_post.topic_id, target_type: 'Topic', username: another_user.username
|
||||
}
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: another_post.topic_id,
|
||||
target_type: "Topic",
|
||||
username: another_user.username,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
expect(JSON.parse(response.body)['error']).to eq(
|
||||
I18n.t('discourse_assign.too_many_assigns', username: another_user.username, max: max_assigns)
|
||||
expect(JSON.parse(response.body)["error"]).to eq(
|
||||
I18n.t(
|
||||
"discourse_assign.too_many_assigns",
|
||||
username: another_user.username,
|
||||
max: max_assigns,
|
||||
),
|
||||
)
|
||||
end
|
||||
|
||||
it 'fails with a specific error message if the topic is a PM and the assignee can not see it' do
|
||||
it "fails with a specific error message if the topic is a PM and the assignee can not see it" do
|
||||
pm = Fabricate(:private_message_post, user: user).topic
|
||||
another_user = Fabricate(:user)
|
||||
add_to_assign_allowed_group(another_user)
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: pm.id, target_type: 'Topic', username: another_user.username
|
||||
}
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: pm.id,
|
||||
target_type: "Topic",
|
||||
username: another_user.username,
|
||||
}
|
||||
|
||||
expect(response.parsed_body['error']).to eq(
|
||||
I18n.t('discourse_assign.forbidden_assignee_not_pm_participant', username: another_user.username)
|
||||
expect(response.parsed_body["error"]).to eq(
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_assignee_not_pm_participant",
|
||||
username: another_user.username,
|
||||
),
|
||||
)
|
||||
end
|
||||
|
||||
it 'fails with a specific error message if the topic is not a PM and the assignee can not see it' do
|
||||
it "fails with a specific error message if the topic is not a PM and the assignee can not see it" do
|
||||
topic = Fabricate(:topic, category: Fabricate(:private_category, group: Fabricate(:group)))
|
||||
another_user = Fabricate(:user)
|
||||
add_to_assign_allowed_group(another_user)
|
||||
put '/assign/assign.json', params: {
|
||||
target_id: topic.id, target_type: "Topic", username: another_user.username
|
||||
}
|
||||
put "/assign/assign.json",
|
||||
params: {
|
||||
target_id: topic.id,
|
||||
target_type: "Topic",
|
||||
username: another_user.username,
|
||||
}
|
||||
|
||||
expect(response.parsed_body['error']).to eq(
|
||||
I18n.t('discourse_assign.forbidden_assignee_cant_see_topic', username: another_user.username)
|
||||
expect(response.parsed_body["error"]).to eq(
|
||||
I18n.t(
|
||||
"discourse_assign.forbidden_assignee_cant_see_topic",
|
||||
username: another_user.username,
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assigned' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
describe "#assigned" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -216,40 +263,44 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'lists topics ordered by user' do
|
||||
get '/assign/assigned.json'
|
||||
expect(JSON.parse(response.body)['topics'].map { |t| t['id'] }).to match_array([post2.topic_id, post1.topic_id, post3.topic_id])
|
||||
it "lists topics ordered by user" do
|
||||
get "/assign/assigned.json"
|
||||
expect(JSON.parse(response.body)["topics"].map { |t| t["id"] }).to match_array(
|
||||
[post2.topic_id, post1.topic_id, post3.topic_id],
|
||||
)
|
||||
|
||||
get '/assign/assigned.json', params: { limit: 2 }
|
||||
expect(JSON.parse(response.body)['topics'].map { |t| t['id'] }).to match_array([post3.topic_id, post2.topic_id])
|
||||
get "/assign/assigned.json", params: { limit: 2 }
|
||||
expect(JSON.parse(response.body)["topics"].map { |t| t["id"] }).to match_array(
|
||||
[post3.topic_id, post2.topic_id],
|
||||
)
|
||||
|
||||
get '/assign/assigned.json', params: { offset: 2 }
|
||||
expect(JSON.parse(response.body)['topics'].map { |t| t['id'] }).to match_array([post1.topic_id])
|
||||
get "/assign/assigned.json", params: { offset: 2 }
|
||||
expect(JSON.parse(response.body)["topics"].map { |t| t["id"] }).to match_array(
|
||||
[post1.topic_id],
|
||||
)
|
||||
end
|
||||
|
||||
context "with custom allowed groups" do
|
||||
let(:custom_allowed_group) { Fabricate(:group, name: 'mygroup') }
|
||||
let(:custom_allowed_group) { Fabricate(:group, name: "mygroup") }
|
||||
let(:other_user) { Fabricate(:user, groups: [custom_allowed_group]) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_allowed_on_groups += "|#{custom_allowed_group.id}"
|
||||
end
|
||||
before { SiteSetting.assign_allowed_on_groups += "|#{custom_allowed_group.id}" }
|
||||
|
||||
it 'works for admins' do
|
||||
get '/assign/assigned.json'
|
||||
it "works for admins" do
|
||||
get "/assign/assigned.json"
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it 'does not work for other groups' do
|
||||
it "does not work for other groups" do
|
||||
sign_in(other_user)
|
||||
get '/assign/assigned.json'
|
||||
get "/assign/assigned.json"
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#group_members' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
describe "#group_members" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -264,12 +315,14 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
Assigner.new(post3.topic, user).assign(user)
|
||||
end
|
||||
|
||||
it 'list members order by assignments_count' do
|
||||
it "list members order by assignments_count" do
|
||||
sign_in(user)
|
||||
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.status).to eq(200)
|
||||
expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user.id, user2.id])
|
||||
expect(JSON.parse(response.body)["members"].map { |m| m["id"] }).to match_array(
|
||||
[user.id, user2.id],
|
||||
)
|
||||
end
|
||||
|
||||
it "doesn't include members with no assignments" do
|
||||
|
@ -278,23 +331,27 @@ RSpec.describe DiscourseAssign::AssignController do
|
|||
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.status).to eq(200)
|
||||
expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user.id, user2.id])
|
||||
expect(JSON.parse(response.body)["members"].map { |m| m["id"] }).to match_array(
|
||||
[user.id, user2.id],
|
||||
)
|
||||
end
|
||||
|
||||
it "returns members as according to filter" do
|
||||
sign_in(user)
|
||||
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'a' }
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: "a" }
|
||||
expect(response.status).to eq(200)
|
||||
expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user.id, user2.id])
|
||||
expect(JSON.parse(response.body)["members"].map { |m| m["id"] }).to match_array(
|
||||
[user.id, user2.id],
|
||||
)
|
||||
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'david' }
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: "david" }
|
||||
expect(response.status).to eq(200)
|
||||
expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user2.id])
|
||||
expect(JSON.parse(response.body)["members"].map { |m| m["id"] }).to match_array([user2.id])
|
||||
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'Tylor' }
|
||||
get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: "Tylor" }
|
||||
expect(response.status).to eq(200)
|
||||
expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user2.id])
|
||||
expect(JSON.parse(response.body)["members"].map { |m| m["id"] }).to match_array([user2.id])
|
||||
end
|
||||
|
||||
it "404 error to non-group-members" do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe ListController do
|
||||
before { SiteSetting.assign_enabled = true }
|
||||
|
@ -11,12 +11,12 @@ describe ListController do
|
|||
let(:admin) { Fabricate(:admin) }
|
||||
let(:post) { Fabricate(:post) }
|
||||
|
||||
describe 'only allow users from allowed groups' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
describe "only allow users from allowed groups" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
it 'filters requests where current_user is not member of an allowed group' do
|
||||
it "filters requests where current_user is not member of an allowed group" do
|
||||
sign_in(user)
|
||||
SiteSetting.assign_allowed_on_groups = ''
|
||||
SiteSetting.assign_allowed_on_groups = ""
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.status).to eq(403)
|
||||
|
@ -25,7 +25,7 @@ describe ListController do
|
|||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it 'as an anon user' do
|
||||
it "as an anon user" do
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.status).to eq(403)
|
||||
|
||||
|
@ -33,7 +33,7 @@ describe ListController do
|
|||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it 'as an admin user' do
|
||||
it "as an admin user" do
|
||||
sign_in(admin)
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.status).to eq(200)
|
||||
|
@ -43,8 +43,8 @@ describe ListController do
|
|||
end
|
||||
end
|
||||
|
||||
context '#group_topics_assigned' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
context "#group_topics_assigned" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -62,30 +62,30 @@ describe ListController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'returns user-assigned-topics-list of users in the assigned_allowed_group and doesnt include deleted topic' do
|
||||
it "returns user-assigned-topics-list of users in the assigned_allowed_group and doesnt include deleted topic" do
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['assigned_to_user']['id'] }).to match_array([user.id])
|
||||
expect(
|
||||
JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["assigned_to_user"]["id"] },
|
||||
).to match_array([user.id])
|
||||
end
|
||||
|
||||
it 'returns user-assigned-topics-list of users in the assigned_allowed_group and doesnt include inactive topics' do
|
||||
it "returns user-assigned-topics-list of users in the assigned_allowed_group and doesnt include inactive topics" do
|
||||
Assignment.where(assigned_to: user, target: topic1).update_all(active: false)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
expect(response.parsed_body['topic_list']['topics']).to be_empty
|
||||
expect(response.parsed_body["topic_list"]["topics"]).to be_empty
|
||||
end
|
||||
|
||||
it 'returns empty user-assigned-topics-list for users not in the assigned_allowed_group' do
|
||||
it "returns empty user-assigned-topics-list for users not in the assigned_allowed_group" do
|
||||
ids = []
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
JSON.parse(response.body)['topic_list']['topics'].each do |t|
|
||||
if t['assigned_to_user']['id'] == user2.id
|
||||
ids.push(t['assigned_to_user']['id'])
|
||||
end
|
||||
JSON.parse(response.body)["topic_list"]["topics"].each do |t|
|
||||
ids.push(t["assigned_to_user"]["id"]) if t["assigned_to_user"]["id"] == user2.id
|
||||
end
|
||||
expect(ids).to be_empty
|
||||
end
|
||||
|
||||
it 'doesnt returns deleted topics' do
|
||||
it "doesnt returns deleted topics" do
|
||||
sign_in(admin)
|
||||
|
||||
Assigner.new(topic, user).assign(user)
|
||||
|
@ -97,18 +97,16 @@ describe ListController do
|
|||
id = 0
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json"
|
||||
|
||||
JSON.parse(response.body)['topic_list']['topics'].each do |t|
|
||||
if t['id'] == topic.id
|
||||
id = t.id
|
||||
end
|
||||
JSON.parse(response.body)["topic_list"]["topics"].each do |t|
|
||||
id = t.id if t["id"] == topic.id
|
||||
end
|
||||
|
||||
expect(id).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context '#sorting messages_assigned and group_topics_assigned' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
context "#sorting messages_assigned and group_topics_assigned" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -128,7 +126,7 @@ describe ListController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'group_topics_assigned returns sorted topicsList' do
|
||||
it "group_topics_assigned returns sorted topicsList" do
|
||||
topic1.bumped_at = Time.now
|
||||
topic2.bumped_at = 1.day.ago
|
||||
topic3.bumped_at = 3.day.ago
|
||||
|
@ -146,25 +144,37 @@ describe ListController do
|
|||
topic3.save!
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=posts"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic2.id, topic1.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic2.id, topic1.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=views"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic1.id, topic2.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic1.id, topic2.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=activity"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic2.id, topic1.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic2.id, topic1.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=posts&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic1.id, topic2.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic1.id, topic2.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=views&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic2.id, topic1.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic2.id, topic1.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json?order=activity&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([ topic1.id, topic2.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic2.id, topic3.id],
|
||||
)
|
||||
end
|
||||
|
||||
it 'messages_assigned returns sorted topicsList' do
|
||||
it "messages_assigned returns sorted topicsList" do
|
||||
topic1.bumped_at = Time.now
|
||||
topic3.bumped_at = 3.day.ago
|
||||
|
||||
|
@ -178,27 +188,39 @@ describe ListController do
|
|||
topic3.reload
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=posts"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=views"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic1.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic1.id],
|
||||
)
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=activity"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic1.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic1.id],
|
||||
)
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=posts&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic3.id, topic1.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic3.id, topic1.id],
|
||||
)
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=views&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json?order=activity&ascending=true"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id, topic3.id])
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic3.id],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering of topics as per parameter' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
context "filtering of topics as per parameter" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -222,44 +244,66 @@ describe ListController do
|
|||
|
||||
after { SearchIndexer.disable }
|
||||
|
||||
it 'returns topics as per filter for #group_topics_assigned' do
|
||||
topic1.title = 'QUnit testing is love'
|
||||
topic2.title = 'RSpec testing is too fun'
|
||||
topic3.title = 'Testing is main part of programming'
|
||||
it "returns topics as per filter for #group_topics_assigned" do
|
||||
topic1.title = "QUnit testing is love"
|
||||
topic2.title = "RSpec testing is too fun"
|
||||
topic3.title = "Testing is main part of programming"
|
||||
|
||||
topic1.save!
|
||||
topic2.save!
|
||||
topic3.save!
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json", params: { search: 'Testing' }
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id, topic2.id, topic3.id])
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json",
|
||||
params: {
|
||||
search: "Testing",
|
||||
}
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic2.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json", params: { search: 'RSpec' }
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic2.id])
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json",
|
||||
params: {
|
||||
search: "RSpec",
|
||||
}
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic2.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json", params: { search: 'love' }
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id])
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json",
|
||||
params: {
|
||||
search: "love",
|
||||
}
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id],
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns topics as per filter for #group_topics_assigned' do
|
||||
topic1.title = 'QUnit testing is love'
|
||||
topic2.title = 'RSpec testing is too fun'
|
||||
topic3.title = 'Testing is main part of programming'
|
||||
it "returns topics as per filter for #group_topics_assigned" do
|
||||
topic1.title = "QUnit testing is love"
|
||||
topic2.title = "RSpec testing is too fun"
|
||||
topic3.title = "Testing is main part of programming"
|
||||
|
||||
topic1.save!
|
||||
topic2.save!
|
||||
topic3.save!
|
||||
|
||||
get "/topics/messages-assigned/#{user.username}.json", params: { search: 'Testing' }
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id, topic3.id])
|
||||
get "/topics/messages-assigned/#{user.username}.json", params: { search: "Testing" }
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id, topic3.id],
|
||||
)
|
||||
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json", params: { search: 'love' }
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['id'] }).to match_array([topic1.id])
|
||||
get "/topics/group-topics-assigned/#{get_assigned_allowed_group_name}.json",
|
||||
params: {
|
||||
search: "love",
|
||||
}
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to match_array(
|
||||
[topic1.id],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context '#messages_assigned' do
|
||||
include_context 'A group that is allowed to assign'
|
||||
context "#messages_assigned" do
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
fab!(:post1) { Fabricate(:post) }
|
||||
fab!(:post2) { Fabricate(:post) }
|
||||
|
@ -273,14 +317,16 @@ describe ListController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'returns user-assigned-topics-list of given user' do
|
||||
it "returns user-assigned-topics-list of given user" do
|
||||
get "/topics/messages-assigned/#{user.username_lower}.json"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics'].map { |t| t['assigned_to_user']['id'] }).to match_array([user.id])
|
||||
expect(
|
||||
JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["assigned_to_user"]["id"] },
|
||||
).to match_array([user.id])
|
||||
end
|
||||
|
||||
it 'returns empty user-assigned-topics-list for given user not in the assigned_allowed_group' do
|
||||
it "returns empty user-assigned-topics-list for given user not in the assigned_allowed_group" do
|
||||
get "/topics/messages-assigned/#{user2.username_lower}.json"
|
||||
expect(JSON.parse(response.body)['topic_list']['topics']).to be_empty
|
||||
expect(JSON.parse(response.body)["topic_list"]["topics"]).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,11 +27,8 @@ describe FlaggedTopicSerializer do
|
|||
|
||||
context "when there is a user assignment" do
|
||||
let(:topic) do
|
||||
topic = Fabricate(:topic,
|
||||
topic_allowed_users: [
|
||||
Fabricate.build(:topic_allowed_user, user: user)
|
||||
]
|
||||
)
|
||||
topic =
|
||||
Fabricate(:topic, topic_allowed_users: [Fabricate.build(:topic_allowed_user, user: user)])
|
||||
|
||||
topic.posts << Fabricate(:post)
|
||||
|
||||
|
@ -42,24 +39,28 @@ describe FlaggedTopicSerializer do
|
|||
it "includes the assigned_to_user attribute" do
|
||||
json = FlaggedTopicSerializer.new(topic, scope: guardian).as_json
|
||||
|
||||
expect(json[:flagged_topic][:assigned_to_user]).to match({
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
assign_icon: "user-plus",
|
||||
avatar_template: /letter_avatar_proxy.*/,
|
||||
assign_path: "/u/#{user.username}/activity/assigned",
|
||||
})
|
||||
expect(json[:flagged_topic][:assigned_to_user]).to match(
|
||||
{
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
assign_icon: "user-plus",
|
||||
avatar_template: /letter_avatar_proxy.*/,
|
||||
assign_path: "/u/#{user.username}/activity/assigned",
|
||||
},
|
||||
)
|
||||
expect(json[:flagged_topic]).to_not have_key(:assigned_to_group)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a group assignment" do
|
||||
let(:topic) do
|
||||
topic = Fabricate(:topic,
|
||||
topic_allowed_groups: [
|
||||
Fabricate.build(:topic_allowed_group, group: assign_allowed_group)
|
||||
]
|
||||
)
|
||||
topic =
|
||||
Fabricate(
|
||||
:topic,
|
||||
topic_allowed_groups: [
|
||||
Fabricate.build(:topic_allowed_group, group: assign_allowed_group),
|
||||
],
|
||||
)
|
||||
|
||||
topic.posts << Fabricate(:post)
|
||||
|
||||
|
@ -70,15 +71,17 @@ describe FlaggedTopicSerializer do
|
|||
it "includes the assigned_to_group attribute" do
|
||||
json = FlaggedTopicSerializer.new(topic, scope: guardian).as_json
|
||||
|
||||
expect(json[:flagged_topic][:assigned_to_group]).to match({
|
||||
name: assign_allowed_group.name,
|
||||
flair_bg_color: assign_allowed_group.flair_bg_color,
|
||||
flair_color: assign_allowed_group.flair_color,
|
||||
flair_icon: assign_allowed_group.flair_icon,
|
||||
flair_upload_id: assign_allowed_group.flair_upload_id,
|
||||
assign_icon: "group-plus",
|
||||
assign_path: "/g/#{assign_allowed_group.name}/assigned/everyone",
|
||||
})
|
||||
expect(json[:flagged_topic][:assigned_to_group]).to match(
|
||||
{
|
||||
name: assign_allowed_group.name,
|
||||
flair_bg_color: assign_allowed_group.flair_bg_color,
|
||||
flair_color: assign_allowed_group.flair_color,
|
||||
flair_icon: assign_allowed_group.flair_icon,
|
||||
flair_upload_id: assign_allowed_group.flair_upload_id,
|
||||
assign_icon: "group-plus",
|
||||
assign_path: "/g/#{assign_allowed_group.name}/assigned/everyone",
|
||||
},
|
||||
)
|
||||
expect(json[:flagged_topic]).to_not have_key(:assigned_to_user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe GroupShowSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe PostSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
@ -9,7 +9,7 @@ describe PostSerializer do
|
|||
fab!(:post) { Fabricate(:post, topic: topic) }
|
||||
let(:guardian) { Guardian.new(user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe SuggestedTopicSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
RSpec.describe TopicListSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
let(:private_message_topic) do
|
||||
topic = Fabricate(:private_message_topic,
|
||||
topic_allowed_users: [
|
||||
Fabricate.build(:topic_allowed_user, user: user)
|
||||
]
|
||||
)
|
||||
topic =
|
||||
Fabricate(
|
||||
:private_message_topic,
|
||||
topic_allowed_users: [Fabricate.build(:topic_allowed_user, user: user)],
|
||||
)
|
||||
topic.posts << Fabricate(:post)
|
||||
topic
|
||||
end
|
||||
|
||||
let(:assigned_topic) do
|
||||
topic = Fabricate(:private_message_topic,
|
||||
topic_allowed_users: [
|
||||
Fabricate.build(:topic_allowed_user, user: user)
|
||||
]
|
||||
)
|
||||
topic =
|
||||
Fabricate(
|
||||
:private_message_topic,
|
||||
topic_allowed_users: [Fabricate.build(:topic_allowed_user, user: user)],
|
||||
)
|
||||
|
||||
topic.posts << Fabricate(:post)
|
||||
|
||||
|
@ -32,77 +32,67 @@ RSpec.describe TopicListSerializer do
|
|||
let(:guardian) { Guardian.new(user) }
|
||||
let(:serializer) { TopicListSerializer.new(topic_list, scope: guardian) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
add_to_assign_allowed_group(user)
|
||||
end
|
||||
|
||||
describe '#assigned_messages_count' do
|
||||
describe "#assigned_messages_count" do
|
||||
let(:topic_list) do
|
||||
TopicQuery.new(user, assigned: user.username).list_private_messages_assigned(user)
|
||||
end
|
||||
|
||||
before do
|
||||
assigned_topic
|
||||
before { assigned_topic }
|
||||
|
||||
it "should include right attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(1)
|
||||
end
|
||||
|
||||
it 'should include right attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(1)
|
||||
end
|
||||
describe "when not viewing assigned list" do
|
||||
let(:topic_list) { TopicQuery.new(user).list_private_messages_assigned(user) }
|
||||
|
||||
describe 'when not viewing assigned list' do
|
||||
let(:topic_list) do
|
||||
TopicQuery.new(user).list_private_messages_assigned(user)
|
||||
end
|
||||
|
||||
describe 'as an admin user' do
|
||||
describe "as an admin user" do
|
||||
let(:guardian) { Guardian.new(Fabricate(:admin)) }
|
||||
|
||||
it 'should not include the attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(nil)
|
||||
it "should not include the attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'as an anon user' do
|
||||
describe "as an anon user" do
|
||||
let(:guardian) { Guardian.new }
|
||||
|
||||
it 'should not include the attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(nil)
|
||||
it "should not include the attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'viewing another user' do
|
||||
describe 'as an anon user' do
|
||||
describe "viewing another user" do
|
||||
describe "as an anon user" do
|
||||
let(:guardian) { Guardian.new }
|
||||
|
||||
it 'should not include the attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(nil)
|
||||
it "should not include the attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'as a staff' do
|
||||
let(:admin) { Fabricate(:admin, groups: [Group.find_by(name: 'staff')]) }
|
||||
describe "as a staff" do
|
||||
let(:admin) { Fabricate(:admin, groups: [Group.find_by(name: "staff")]) }
|
||||
let(:guardian) { Guardian.new(admin) }
|
||||
|
||||
it 'should include the right attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(1)
|
||||
it "should include the right attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'as a normal user' do
|
||||
describe "as a normal user" do
|
||||
let(:guardian) { Guardian.new(Fabricate(:user)) }
|
||||
|
||||
it 'should not include the attribute' do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count])
|
||||
.to eq(nil)
|
||||
it "should not include the attribute" do
|
||||
expect(serializer.as_json[:topic_list][:assigned_messages_count]).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
RSpec.describe TopicViewSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
@ -9,7 +9,7 @@ RSpec.describe TopicViewSerializer do
|
|||
fab!(:post) { Fabricate(:post, topic: topic) }
|
||||
let(:guardian) { Guardian.new(user) }
|
||||
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
|
@ -26,7 +26,9 @@ RSpec.describe TopicViewSerializer do
|
|||
it "includes assigned group in serializer" do
|
||||
Assigner.new(topic, user).assign(assign_allowed_group)
|
||||
serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian)
|
||||
expect(serializer.as_json[:topic_view][:assigned_to_group][:name]).to eq(assign_allowed_group.name)
|
||||
expect(serializer.as_json[:topic_view][:assigned_to_group][:name]).to eq(
|
||||
assign_allowed_group.name,
|
||||
)
|
||||
expect(serializer.as_json[:topic_view][:assigned_to_user]).to be nil
|
||||
end
|
||||
|
||||
|
@ -39,6 +41,8 @@ RSpec.describe TopicViewSerializer do
|
|||
it "includes indirectly_assigned_to notes in serializer" do
|
||||
Assigner.new(post, user).assign(user, note: "note me down")
|
||||
serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian)
|
||||
expect(serializer.as_json[:topic_view][:indirectly_assigned_to][post.id][:assignment_note]).to eq("note me down")
|
||||
expect(
|
||||
serializer.as_json[:topic_view][:indirectly_assigned_to][post.id][:assignment_note],
|
||||
).to eq("note me down")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require_relative '../support/assign_allowed_group'
|
||||
require "rails_helper"
|
||||
require_relative "../support/assign_allowed_group"
|
||||
|
||||
describe UserBookmarkBaseSerializer do
|
||||
include_context 'A group that is allowed to assign'
|
||||
include_context "A group that is allowed to assign"
|
||||
|
||||
before do
|
||||
SiteSetting.assign_enabled = true
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
shared_context 'A group that is allowed to assign' do
|
||||
fab!(:assign_allowed_group) { Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:everyone]) }
|
||||
|
||||
before do
|
||||
SiteSetting.assign_allowed_on_groups += "|#{assign_allowed_group.id}"
|
||||
shared_context "A group that is allowed to assign" do
|
||||
fab!(:assign_allowed_group) do
|
||||
Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:everyone])
|
||||
end
|
||||
|
||||
before { SiteSetting.assign_allowed_on_groups += "|#{assign_allowed_group.id}" }
|
||||
|
||||
def add_to_assign_allowed_group(user)
|
||||
assign_allowed_group.add(user)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue