FEATURE: Allow admins to reply without topic bump
This commit is contained in:
parent
6ec92d5845
commit
ef4b9f98c1
|
@ -53,7 +53,8 @@ function loadDraft(store, opts) {
|
|||
composerTime: draft.composerTime,
|
||||
typingTime: draft.typingTime,
|
||||
whisper: draft.whisper,
|
||||
tags: draft.tags
|
||||
tags: draft.tags,
|
||||
noBump: draft.noBump
|
||||
});
|
||||
return composer;
|
||||
}
|
||||
|
@ -194,6 +195,13 @@ export default Ember.Controller.extend({
|
|||
}
|
||||
},
|
||||
|
||||
@computed("model.noBump")
|
||||
topicBumpText(noBump) {
|
||||
if (noBump) {
|
||||
return I18n.t("composer.no_topic_bump");
|
||||
}
|
||||
},
|
||||
|
||||
@computed
|
||||
isStaffUser() {
|
||||
const currentUser = this.currentUser;
|
||||
|
|
|
@ -41,7 +41,8 @@ const CLOSED = "closed",
|
|||
composer_open_duration_msecs: "composerTime",
|
||||
tags: "tags",
|
||||
featured_link: "featuredLink",
|
||||
shared_draft: "sharedDraft"
|
||||
shared_draft: "sharedDraft",
|
||||
no_bump: "noBump"
|
||||
},
|
||||
_edit_topic_serializer = {
|
||||
title: "topic.title",
|
||||
|
@ -71,6 +72,7 @@ const SAVE_ICONS = {
|
|||
const Composer = RestModel.extend({
|
||||
_categoryId: null,
|
||||
unlistTopic: false,
|
||||
noBump: false,
|
||||
|
||||
archetypes: function() {
|
||||
return this.site.get("archetypes");
|
||||
|
@ -608,7 +610,8 @@ const Composer = RestModel.extend({
|
|||
composerTotalOpened: opts.composerTime,
|
||||
typingTime: opts.typingTime,
|
||||
whisper: opts.whisper,
|
||||
tags: opts.tags
|
||||
tags: opts.tags,
|
||||
noBump: opts.noBump
|
||||
});
|
||||
|
||||
if (opts.post) {
|
||||
|
@ -714,7 +717,8 @@ const Composer = RestModel.extend({
|
|||
typingTime: 0,
|
||||
composerOpened: null,
|
||||
composerTotalOpened: 0,
|
||||
featuredLink: null
|
||||
featuredLink: null,
|
||||
noBump: false
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -964,7 +968,8 @@ const Composer = RestModel.extend({
|
|||
usernames: this.get("targetUsernames"),
|
||||
composerTime: this.get("composerTime"),
|
||||
typingTime: this.get("typingTime"),
|
||||
tags: this.get("tags")
|
||||
tags: this.get("tags"),
|
||||
noBump: this.get("noBump")
|
||||
};
|
||||
|
||||
this.set("draftStatus", I18n.t("composer.saving_draft_tip"));
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
{{#if whisperOrUnlistTopicText}}
|
||||
<span class='whisper'>({{whisperOrUnlistTopicText}})</span>
|
||||
{{/if}}
|
||||
{{#if topicBumpText}}
|
||||
<span class="no-bump">{{topicBumpText}}</span>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
{{#if canEdit}}
|
||||
|
@ -120,6 +123,11 @@
|
|||
{{d-icon "eye-slash"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{#if topicBumpText}}
|
||||
<span class="no-bump">
|
||||
{{d-icon "anchor"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
||||
|
|
|
@ -192,6 +192,17 @@ export default DropdownSelectBoxComponent.extend({
|
|||
});
|
||||
}
|
||||
|
||||
const currentUser = Discourse.User.current();
|
||||
|
||||
if (action === REPLY && currentUser && currentUser.get("staff")) {
|
||||
items.push({
|
||||
name: I18n.t("composer.composer_actions.toggle_topic_bump.label"),
|
||||
description: I18n.t("composer.composer_actions.toggle_topic_bump.desc"),
|
||||
icon: "anchor",
|
||||
id: "toggle_topic_bump"
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
|
@ -234,6 +245,10 @@ export default DropdownSelectBoxComponent.extend({
|
|||
model.toggleProperty("whisper");
|
||||
},
|
||||
|
||||
toggleTopicBumpSelected(options, model) {
|
||||
model.toggleProperty("noBump");
|
||||
},
|
||||
|
||||
replyToTopicSelected(options) {
|
||||
options.action = REPLY;
|
||||
options.topic = _topicSnapshot;
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
}
|
||||
|
||||
.whisper,
|
||||
.no-bump,
|
||||
.display-edit-reason {
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
|
@ -653,6 +653,11 @@ class PostsController < ApplicationController
|
|||
result[:is_warning] = false
|
||||
end
|
||||
|
||||
if params[:no_bump] == "true"
|
||||
raise Discourse::InvalidParameters.new(:no_bump) unless guardian.can_skip_bump?
|
||||
result[:no_bump] = true
|
||||
end
|
||||
|
||||
if params[:shared_draft] == 'true'
|
||||
raise Discourse::InvalidParameters.new(:shared_draft) unless guardian.can_create_shared_draft?
|
||||
|
||||
|
|
|
@ -1318,6 +1318,7 @@ en:
|
|||
whisper: "whisper"
|
||||
unlist: "unlisted"
|
||||
blockquote_text: "Blockquote"
|
||||
no_topic_bump: "(no bump)"
|
||||
|
||||
add_warning: "This is an official warning."
|
||||
toggle_whisper: "Toggle Whisper"
|
||||
|
@ -1437,6 +1438,9 @@ en:
|
|||
shared_draft:
|
||||
label: "Shared Draft"
|
||||
desc: "Draft a topic that will only be visible to staff"
|
||||
toggle_topic_bump:
|
||||
label: "Toggle topic bump"
|
||||
desc: "Reply without changing the topic's bump date"
|
||||
|
||||
notifications:
|
||||
tooltip:
|
||||
|
|
|
@ -255,4 +255,8 @@ module PostGuardian
|
|||
def can_unhide?(post)
|
||||
post.try(:hidden) && is_staff?
|
||||
end
|
||||
|
||||
def can_skip_bump?
|
||||
is_staff?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1055,6 +1055,67 @@ describe PostsController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "topic bump" do
|
||||
shared_examples "it works" do
|
||||
let(:original_bumped_at) { 1.day.ago }
|
||||
let!(:topic) { Fabricate(:topic, bumped_at: original_bumped_at) }
|
||||
|
||||
it "should be able to skip topic bumping" do
|
||||
post "/posts.json", params: {
|
||||
raw: 'this is the test content',
|
||||
topic_id: topic.id,
|
||||
no_bump: true
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(topic.reload.bumped_at).to be_within_one_second_of(original_bumped_at)
|
||||
end
|
||||
|
||||
it "should be able to post with topic bumping" do
|
||||
post "/posts.json", params: {
|
||||
raw: 'this is the test content',
|
||||
topic_id: topic.id
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(topic.reload.bumped_at).to eq(topic.posts.last.created_at)
|
||||
end
|
||||
end
|
||||
|
||||
context "admins" do
|
||||
before do
|
||||
sign_in(Fabricate(:admin))
|
||||
end
|
||||
|
||||
include_examples "it works"
|
||||
end
|
||||
|
||||
context "moderators" do
|
||||
before do
|
||||
sign_in(Fabricate(:moderator))
|
||||
end
|
||||
|
||||
include_examples "it works"
|
||||
end
|
||||
|
||||
context "users" do
|
||||
let(:topic) { Fabricate(:topic) }
|
||||
|
||||
[:user, :trust_level_4].each do |user|
|
||||
it "will raise an error for #{user}" do
|
||||
sign_in(Fabricate(user))
|
||||
post "/posts.json", params: {
|
||||
raw: 'this is the test content',
|
||||
topic_id: topic.id,
|
||||
no_bump: true
|
||||
}
|
||||
expect(response.status).to eq(400)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '#revisions' do
|
||||
|
@ -1524,5 +1585,4 @@ describe PostsController do
|
|||
expect(public_post).not_to be_locked
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
import { acceptance, replaceCurrentUser } from "helpers/qunit-helpers";
|
||||
import { _clearSnapshots } from "select-kit/components/composer-actions";
|
||||
|
||||
acceptance("Composer Actions", {
|
||||
|
@ -25,7 +25,8 @@ QUnit.test("replying to post", async assert => {
|
|||
);
|
||||
assert.equal(composerActions.rowByIndex(2).value(), "reply_to_topic");
|
||||
assert.equal(composerActions.rowByIndex(3).value(), "toggle_whisper");
|
||||
assert.equal(composerActions.rowByIndex(4).value(), undefined);
|
||||
assert.equal(composerActions.rowByIndex(4).value(), "toggle_topic_bump");
|
||||
assert.equal(composerActions.rowByIndex(5).value(), undefined);
|
||||
});
|
||||
|
||||
QUnit.test("replying to post - reply_as_private_message", async assert => {
|
||||
|
@ -179,7 +180,8 @@ QUnit.test("interactions", async assert => {
|
|||
"reply_as_private_message"
|
||||
);
|
||||
assert.equal(composerActions.rowByIndex(3).value(), "toggle_whisper");
|
||||
assert.equal(composerActions.rows().length, 4);
|
||||
assert.equal(composerActions.rowByIndex(4).value(), "toggle_topic_bump");
|
||||
assert.equal(composerActions.rows().length, 5);
|
||||
|
||||
await composerActions.selectRowByValue("reply_to_post");
|
||||
await composerActions.expand();
|
||||
|
@ -199,7 +201,8 @@ QUnit.test("interactions", async assert => {
|
|||
);
|
||||
assert.equal(composerActions.rowByIndex(2).value(), "reply_to_topic");
|
||||
assert.equal(composerActions.rowByIndex(3).value(), "toggle_whisper");
|
||||
assert.equal(composerActions.rows().length, 4);
|
||||
assert.equal(composerActions.rowByIndex(4).value(), "toggle_topic_bump");
|
||||
assert.equal(composerActions.rows().length, 5);
|
||||
|
||||
await composerActions.selectRowByValue("reply_as_new_topic");
|
||||
await composerActions.expand();
|
||||
|
@ -243,3 +246,62 @@ QUnit.test("interactions", async assert => {
|
|||
assert.equal(composerActions.rowByIndex(2).value(), "reply_to_topic");
|
||||
assert.equal(composerActions.rows().length, 3);
|
||||
});
|
||||
|
||||
QUnit.test("replying to post - toggle_topic_bump", async assert => {
|
||||
const composerActions = selectKit(".composer-actions");
|
||||
|
||||
await visit("/t/internationalization-localization/280");
|
||||
await click("article#post_3 button.reply");
|
||||
|
||||
assert.ok(
|
||||
find(".composer-fields .no-bump").length === 0,
|
||||
"no-bump text is not visible"
|
||||
);
|
||||
|
||||
await composerActions.expand();
|
||||
await composerActions.selectRowByValue("toggle_topic_bump");
|
||||
|
||||
assert.equal(
|
||||
find(".composer-fields .no-bump").text(),
|
||||
I18n.t("composer.no_topic_bump"),
|
||||
"no-bump text is visible"
|
||||
);
|
||||
|
||||
await composerActions.expand();
|
||||
await composerActions.selectRowByValue("toggle_topic_bump");
|
||||
|
||||
assert.ok(
|
||||
find(".composer-fields .no-bump").length === 0,
|
||||
"no-bump text is not visible"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("replying to post as staff", async assert => {
|
||||
const composerActions = selectKit(".composer-actions");
|
||||
|
||||
replaceCurrentUser({ staff: true, admin: false });
|
||||
await visit("/t/internationalization-localization/280");
|
||||
await click("article#post_3 button.reply");
|
||||
await composerActions.expand();
|
||||
|
||||
assert.equal(composerActions.rows().length, 5);
|
||||
assert.equal(composerActions.rowByIndex(4).value(), "toggle_topic_bump");
|
||||
});
|
||||
|
||||
QUnit.test("replying to post as regular user", async assert => {
|
||||
const composerActions = selectKit(".composer-actions");
|
||||
|
||||
replaceCurrentUser({ staff: false, admin: false });
|
||||
await visit("/t/internationalization-localization/280");
|
||||
await click("article#post_3 button.reply");
|
||||
await composerActions.expand();
|
||||
|
||||
assert.equal(composerActions.rows().length, 3);
|
||||
Array.from(composerActions.rows()).forEach(row => {
|
||||
assert.notEqual(
|
||||
row.value,
|
||||
"toggle_topic_bump",
|
||||
"toggle button is not visible"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue