FEATURE: new assignable group option instead of messageable (#195)

V1 of group assign was using "who can message" to determine if group can be assigned.

This PR is introducing new separate setting "who can assign"
This commit is contained in:
Krzysztof Kotlarek 2021-09-08 10:30:13 +10:00 committed by GitHub
parent f541158b64
commit 375f7ba78d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 95 additions and 6 deletions

View File

@ -25,7 +25,7 @@ module DiscourseAssign
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).messageable(current_user).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

View File

@ -0,0 +1,13 @@
<div class="control-group">
<label class="control-label">{{i18n "discourse_assign.admin.groups.manage.interaction.assign"}}</label>
<label for="visiblity">{{i18n "discourse_assign.admin.groups.manage.interaction.assignable_levels.title"}}</label>
{{combo-box
name="alias"
valueProperty="value"
value=assignableLevel
content=assignableLevelOptions
class="groups-form-assignable-level"
onChange=(action (mut model.assignable_level))
}}
</div>

View File

@ -0,0 +1,24 @@
import I18n from "I18n";
import { or } from "@ember/object/computed";
import { defineProperty } from "@ember/object";
export default {
name: "assignable-interaction-fields",
setupComponent(args, component) {
this.assignableLevelOptions = [
{ name: I18n.t("groups.alias_levels.nobody"), value: 0 },
{ name: I18n.t("groups.alias_levels.only_admins"), value: 1 },
{ name: I18n.t("groups.alias_levels.mods_and_admins"), value: 2 },
{ name: I18n.t("groups.alias_levels.members_mods_and_admins"), value: 3 },
{ name: I18n.t("groups.alias_levels.owners_mods_and_admins"), value: 4 },
{ name: I18n.t("groups.alias_levels.everyone"), value: 99 },
];
defineProperty(
component,
"assignableLevel",
or("model.assignable_level", "assignableLevelOptions.firstObject.value")
);
},
};

View File

@ -273,6 +273,14 @@ function initialize(api) {
},
});
api.modifyClass("model:group", {
asJSON() {
return Object.assign({}, this._super(...arguments), {
assignable_level: this.assignable_level,
});
},
});
api.modifyClass("controller:topic", {
pluginId: PLUGIN_ID,
@ -442,5 +450,8 @@ export default {
api.addGroupPostSmallActionCode("assigned_group");
api.addGroupPostSmallActionCode("unassigned_group");
});
withPluginApi("0.12.3", (api) => {
api.addUserSearchOption("assignableGroups");
});
},
};

View File

@ -9,8 +9,8 @@
options=(hash
placementStrategy="absolute"
filterPlaceholder=placeholderKey
includeGroups=false
includeMessageableGroups=true
includeGroups=true
assignableGroups=true
groupMembersOf=allowedGroups
maximum=1
autofocus=autofocus

View File

@ -47,6 +47,13 @@ en:
weekly: "Weekly"
monthly: "Monthly"
quarterly: "Quarterly"
admin:
groups:
manage:
interaction:
assign: "Assign"
assignable_levels:
title: "Who can assign this group"
user:
messages:
assigned_title: "Assigned (%{count})"

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddAssignableLevelToGroups < ActiveRecord::Migration[6.1]
def change
add_column :groups, :assignable_level, :integer, default: 0, null: false
end
end

View File

@ -126,7 +126,7 @@ class ::TopicAssigner
end
def allowed_group_ids
@allowed_group_ids ||= Group.messageable(@assigned_by).pluck(:id)
@allowed_group_ids ||= Group.assignable(@assigned_by).pluck(:id)
end
def can_assign_to?(assign_to)

View File

@ -36,10 +36,33 @@ after_initialize do
require 'topic_assigner'
require 'pending_assigns_reminder'
# TODO: Drop when Discourse stable 2.8.0 is released
if respond_to?(:register_group_param)
register_group_param(:assignable_level)
end
if respond_to?(:register_groups_callback_for_users_search_controller_action)
register_groups_callback_for_users_search_controller_action(:assignable_groups) do |groups, user|
groups.assignable(user)
end
end
class ::Topic
has_one :assignment, dependent: :destroy
end
class ::Group
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)
}
end
frequency_field = PendingAssignsReminder::REMINDERS_FREQUENCY
register_editable_user_custom_field frequency_field
User.register_custom_field_type frequency_field, :integer
@ -73,6 +96,10 @@ after_initialize do
scope.can_assign?
end
add_to_serializer(:group_show, :assignable_level) do
object.assignable_level
end
add_to_serializer(:group_show, :can_show_assigned_tab?) do
object.can_show_assigned_tab?
end

View File

@ -4,7 +4,7 @@ require 'rails_helper'
RSpec.describe GroupShowSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:group) { Fabricate(:group, messageable_level: Group::ALIAS_LEVELS[:everyone]) }
fab!(:group) { Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:everyone]) }
fab!(:group_user) { Fabricate(:group_user, group: group, user: user) }
fab!(:topic) { Fabricate(:topic) }
fab!(:post) { Fabricate(:post, topic: topic) }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
shared_context 'A group that is allowed to assign' do
fab!(:assign_allowed_group) { Fabricate(:group, messageable_level: Group::ALIAS_LEVELS[:everyone]) }
fab!(:assign_allowed_group) { Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:everyone]) }
before do
SiteSetting.assign_allowed_on_groups += "|#{assign_allowed_group.id}"