FEATURE: allow category group moderators to pin/unpin topics (#12325)

* FEATURE: allow category group moderators to pin/unpin topics

Category group moderators should be able to pin/unpin any topics within a category where they have appropraite category group moderator permissions.
This commit is contained in:
jbrw
2021-03-09 16:05:11 -05:00
committed by GitHub
parent 4430bc153d
commit ac7773a30d
9 changed files with 122 additions and 48 deletions

View File

@ -47,6 +47,11 @@ export default Controller.extend(ModalFunctionality, {
return I18n.t(name, { categoryLink, until }); return I18n.t(name, { categoryLink, until });
}, },
@discourseComputed("model.details.can_pin_unpin_topic")
canPinGlobally(canPinUnpinTopic) {
return this.currentUser.isElder && canPinUnpinTopic;
},
@discourseComputed("categoryLink") @discourseComputed("categoryLink")
pinMessage(categoryLink) { pinMessage(categoryLink) {
return I18n.t("topic.feature_topic.pin", { categoryLink }); return I18n.t("topic.feature_topic.pin", { categoryLink });

View File

@ -71,6 +71,7 @@
</p> </p>
</div> </div>
</div> </div>
{{#if canPinGlobally}}
<div class="feature-section"> <div class="feature-section">
<div class="desc"> <div class="desc">
<p> <p>
@ -121,6 +122,7 @@
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{/if}}
{{#if currentUser.staff}} {{#if currentUser.staff}}
<div class="feature-section"> <div class="feature-section">
<div class="desc"> <div class="desc">

View File

@ -206,8 +206,13 @@ export default createWidget("topic-admin-menu", {
icon: "far-clock", icon: "far-clock",
label: "actions.timed_update", label: "actions.timed_update",
}); });
}
if (!isPrivateMessage && (topic.get("visible") || featured)) { if (
details.get("can_pin_unpin_topic") &&
!isPrivateMessage &&
(topic.get("visible") || featured)
) {
this.addActionButton({ this.addActionButton({
className: "topic-admin-pin", className: "topic-admin-pin",
buttonClass: "popup-menu-btn", buttonClass: "popup-menu-btn",
@ -217,6 +222,7 @@ export default createWidget("topic-admin-menu", {
}); });
} }
if (this.get("currentUser.canManageTopic")) {
if (this.currentUser.get("staff")) { if (this.currentUser.get("staff")) {
this.addActionButton({ this.addActionButton({
className: "topic-admin-change-timestamp", className: "topic-admin-change-timestamp",

View File

@ -459,3 +459,45 @@ acceptance("Topic with title decorated", function (needs) {
); );
}); });
}); });
acceptance("Topic pinning/unpinning as an admin", function (needs) {
needs.user({ admin: true });
test("Admin pinning topic", async function (assert) {
await visit("/t/topic-for-group-moderators/2480");
await click(".toggle-admin-menu");
await click(".topic-admin-pin .btn");
assert.ok(
exists(".feature-topic .btn-primary"),
"it should show the 'Pin Topic' button"
);
assert.ok(
exists(".make-banner"),
"it should show the 'Banner Topic' button"
);
});
});
acceptance("Topic pinning/unpinning as a group moderator", function (needs) {
needs.user({ moderator: false, admin: false, trust_level: 1 });
test("Group category moderator pinning topic", async function (assert) {
await visit("/t/topic-for-group-moderators/2480");
await click(".toggle-admin-menu");
await click(".topic-admin-pin .btn");
assert.ok(
exists(".feature-topic .btn-primary"),
"it should show the 'Pin Topic' button"
);
assert.ok(
!exists(".make-banner"),
"it should not show the 'Banner Topic' button"
);
});
});

View File

@ -2206,6 +2206,7 @@ export default {
can_publish_page: true, can_publish_page: true,
can_invite_via_email: true, can_invite_via_email: true,
can_toggle_topic_visibility: true, can_toggle_topic_visibility: true,
can_pin_unpin_topic: true,
auto_close_at: null, auto_close_at: null,
auto_close_hours: null, auto_close_hours: null,
auto_close_based_on_last_post: false, auto_close_based_on_last_post: false,
@ -5597,6 +5598,7 @@ export default {
can_toggle_topic_visibility: true, can_toggle_topic_visibility: true,
can_split_merge_topic: true, can_split_merge_topic: true,
can_edit_staff_notes: true, can_edit_staff_notes: true,
can_pin_unpin_topic: true,
can_moderate_category: true, can_moderate_category: true,
participants: [ participants: [
{ {

View File

@ -429,6 +429,8 @@ class TopicsController < ApplicationController
guardian.ensure_can_archive_topic!(@topic) guardian.ensure_can_archive_topic!(@topic)
when 'visible' when 'visible'
guardian.ensure_can_toggle_topic_visibility!(@topic) guardian.ensure_can_toggle_topic_visibility!(@topic)
when 'pinned'
guardian.ensure_can_pin_unpin_topic!(@topic)
else else
guardian.ensure_can_moderate!(@topic) guardian.ensure_can_moderate!(@topic)
end end

View File

@ -21,6 +21,7 @@ class TopicViewDetailsSerializer < ApplicationSerializer
:can_split_merge_topic, :can_split_merge_topic,
:can_edit_staff_notes, :can_edit_staff_notes,
:can_toggle_topic_visibility, :can_toggle_topic_visibility,
:can_pin_unpin_topic,
:can_moderate_category] :can_moderate_category]
end end
@ -149,6 +150,10 @@ class TopicViewDetailsSerializer < ApplicationSerializer
scope.can_toggle_topic_visibility?(object.topic) scope.can_toggle_topic_visibility?(object.topic)
end end
def include_can_pin_unpin_topic?
scope.can_pin_unpin_topic?(object.topic)
end
def can_perform_action_available_to_group_moderators? def can_perform_action_available_to_group_moderators?
@can_perform_action_available_to_group_moderators ||= scope.can_perform_action_available_to_group_moderators?(object.topic) @can_perform_action_available_to_group_moderators ||= scope.can_perform_action_available_to_group_moderators?(object.topic)
end end

View File

@ -239,6 +239,7 @@ module TopicGuardian
alias :can_open_topic? :can_perform_action_available_to_group_moderators? alias :can_open_topic? :can_perform_action_available_to_group_moderators?
alias :can_split_merge_topic? :can_perform_action_available_to_group_moderators? alias :can_split_merge_topic? :can_perform_action_available_to_group_moderators?
alias :can_edit_staff_notes? :can_perform_action_available_to_group_moderators? alias :can_edit_staff_notes? :can_perform_action_available_to_group_moderators?
alias :can_pin_unpin_topic? :can_perform_action_available_to_group_moderators?
def can_move_posts?(topic) def can_move_posts?(topic)
return false if is_silenced? return false if is_silenced?

View File

@ -940,12 +940,21 @@ RSpec.describe TopicsController do
expect(topic.posts.last.action_code).to eq('archived.disabled') expect(topic.posts.last.action_code).to eq('archived.disabled')
end end
it 'should not allow a group moderator to pin a topic' do it 'should allow a group moderator to pin a topic' do
put "/t/#{topic.id}/status.json", params: { put "/t/#{topic.id}/status.json", params: {
status: 'pinned', enabled: 'true' status: 'pinned', enabled: 'true', until: 2.weeks.from_now
} }
expect(response.status).to eq(403) expect(response.status).to eq(200)
expect(topic.reload.pinned_at).to_not eq(nil)
end
it 'should allow a group moderator to unpin a topic' do
put "/t/#{topic.id}/status.json", params: {
status: 'pinned', enabled: 'false'
}
expect(response.status).to eq(200)
expect(topic.reload.pinned_at).to eq(nil) expect(topic.reload.pinned_at).to eq(nil)
end end