mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 06:04:11 +08:00
FEATURE: reply as new message to the same recipients
This commit is contained in:
parent
c01cee4aa6
commit
c76f6856ea
|
@ -57,6 +57,7 @@ export default Ember.Controller.extend({
|
|||
application: Ember.inject.controller(),
|
||||
|
||||
replyAsNewTopicDraft: Em.computed.equal('model.draftKey', Composer.REPLY_AS_NEW_TOPIC_KEY),
|
||||
replyAsNewPrivateMessageDraft: Em.computed.equal('model.draftKey', Composer.REPLY_AS_NEW_PRIVATE_MESSAGE_KEY),
|
||||
checkedMessages: false,
|
||||
messageCount: null,
|
||||
showEditReason: false,
|
||||
|
@ -478,7 +479,7 @@ export default Ember.Controller.extend({
|
|||
}
|
||||
|
||||
// If user "created a new topic/post" or "replied as a new topic" successfully, remove the draft.
|
||||
if (result.responseJson.action === "create_post" || this.get('replyAsNewTopicDraft')) {
|
||||
if (result.responseJson.action === "create_post" || self.get('replyAsNewTopicDraft') || self.get('replyAsNewPrivateMessageDraft')) {
|
||||
this.destroyDraft();
|
||||
}
|
||||
if (this.get('model.action') === 'edit') {
|
||||
|
|
|
@ -656,11 +656,31 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
|||
const quotedText = Quote.build(post, quoteState.buffer);
|
||||
quoteState.clear();
|
||||
|
||||
composerController.open({
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.REPLY_AS_NEW_TOPIC_KEY,
|
||||
categoryId: this.get('model.category.id')
|
||||
}).then(() => {
|
||||
var options;
|
||||
if (this.get('model.isPrivateMessage')) {
|
||||
let users = this.get('model.details.allowed_users');
|
||||
let groups = this.get('model.details.allowed_groups');
|
||||
|
||||
let usernames = [];
|
||||
users.forEach(user => usernames.push(user.username));
|
||||
groups.forEach(group => usernames.push(group.name));
|
||||
usernames = usernames.join();
|
||||
|
||||
options = {
|
||||
action: Composer.PRIVATE_MESSAGE,
|
||||
archetypeId: 'private_message',
|
||||
draftKey: Composer.REPLY_AS_NEW_PRIVATE_MESSAGE_KEY,
|
||||
usernames: usernames
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.REPLY_AS_NEW_TOPIC_KEY,
|
||||
categoryId: this.get('model.category.id')
|
||||
};
|
||||
}
|
||||
|
||||
composerController.open(options).then(() => {
|
||||
return Em.isEmpty(quotedText) ? "" : quotedText;
|
||||
}).then(q => {
|
||||
const postUrl = `${location.protocol}//${location.host}${post.get('url')}`;
|
||||
|
|
|
@ -18,6 +18,7 @@ const CLOSED = 'closed',
|
|||
REPLY = 'reply',
|
||||
EDIT = 'edit',
|
||||
REPLY_AS_NEW_TOPIC_KEY = "reply_as_new_topic",
|
||||
REPLY_AS_NEW_PRIVATE_MESSAGE_KEY = "reply_as_new_private_message",
|
||||
|
||||
// When creating, these fields are moved into the post model from the composer model
|
||||
_create_serializer = {
|
||||
|
@ -814,7 +815,8 @@ Composer.reopenClass({
|
|||
EDIT,
|
||||
|
||||
// Draft key
|
||||
REPLY_AS_NEW_TOPIC_KEY
|
||||
REPLY_AS_NEW_TOPIC_KEY,
|
||||
REPLY_AS_NEW_PRIVATE_MESSAGE_KEY
|
||||
});
|
||||
|
||||
export default Composer;
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
|
||||
{{#if topic.details.can_reply_as_new_topic}}
|
||||
<div class='reply-as-new-topic'>
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_topic'}} title={{i18n 'post.reply_as_new_topic'}}>{{fa-icon "plus"}}{{i18n 'topic.create'}}</a>
|
||||
{{#if topic.isPrivateMessage}}
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_private_message'}} title={{i18n 'post.reply_as_new_private_message'}}>{{fa-icon "plus"}}{{i18n 'user.new_private_message'}}</a>
|
||||
{{else}}
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_topic'}} title={{i18n 'post.reply_as_new_topic'}}>{{fa-icon "plus"}}{{i18n 'topic.create'}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -1707,6 +1707,7 @@ en:
|
|||
wiki_last_edited_on: "wiki last edited on"
|
||||
last_edited_on: "post last edited on"
|
||||
reply_as_new_topic: "Reply as linked Topic"
|
||||
reply_as_new_private_message: "Reply as new message to the same recipients"
|
||||
continue_discussion: "Continuing the discussion from {{postLink}}:"
|
||||
follow_quote: "go to the quoted post"
|
||||
show_full: "Show Full Post"
|
||||
|
|
|
@ -69,7 +69,7 @@ module TopicGuardian
|
|||
end
|
||||
|
||||
def can_reply_as_new_topic?(topic)
|
||||
authenticated? && topic && !topic.private_message? && @user.has_trust_level?(TrustLevel[1])
|
||||
authenticated? && topic && @user.has_trust_level?(TrustLevel[1])
|
||||
end
|
||||
|
||||
def can_see_deleted_topics?
|
||||
|
|
|
@ -218,6 +218,7 @@ describe Guardian do
|
|||
describe 'can_reply_as_new_topic' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:topic) { Fabricate(:topic) }
|
||||
let(:private_message) { Fabricate(:private_message_topic) }
|
||||
|
||||
it "returns false for a non logged in user" do
|
||||
expect(Guardian.new(nil).can_reply_as_new_topic?(topic)).to be_falsey
|
||||
|
@ -235,6 +236,10 @@ describe Guardian do
|
|||
it "returns true for a trusted user" do
|
||||
expect(Guardian.new(user).can_reply_as_new_topic?(topic)).to be_truthy
|
||||
end
|
||||
|
||||
it "returns true for a private message" do
|
||||
expect(Guardian.new(user).can_reply_as_new_topic?(private_message)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe 'can_see_post_actors?' do
|
||||
|
|
|
@ -72,3 +72,57 @@ test("Marking a topic as wiki", () => {
|
|||
ok(find('a.wiki').length === 1, 'it shows the wiki icon');
|
||||
});
|
||||
});
|
||||
|
||||
test("Reply as new topic", () => {
|
||||
visit("/t/internationalization-localization/280");
|
||||
click("button.share:eq(0)");
|
||||
click(".reply-as-new-topic a");
|
||||
|
||||
andThen(() => {
|
||||
ok(exists('.d-editor-input'), 'the composer input is visible');
|
||||
|
||||
equal(
|
||||
find('.d-editor-input').val().trim(),
|
||||
"Continuing the discussion from [Internationalization / localization](http://localhost:3000/t/internationalization-localization/280):",
|
||||
"it fills composer with the ring string"
|
||||
);
|
||||
|
||||
equal(
|
||||
find('#select2-chosen-1').text().trim(), "feature",
|
||||
"it fills category selector with the right category"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("Reply as new message", () => {
|
||||
visit("/t/pm-for-testing/12");
|
||||
click("button.share:eq(0)");
|
||||
click(".reply-as-new-topic a");
|
||||
|
||||
andThen(() => {
|
||||
ok(exists('.d-editor-input'), 'the composer input is visible');
|
||||
|
||||
equal(
|
||||
find('.d-editor-input').val().trim(),
|
||||
"Continuing the discussion from [PM for testing](http://localhost:3000/t/pm-for-testing/12):",
|
||||
"it fills composer with the ring string"
|
||||
);
|
||||
|
||||
const targets = find('.item span', '.composer-fields');
|
||||
|
||||
equal(
|
||||
$(targets[0]).text(), "someguy",
|
||||
"it fills up the composer with the right user to start the PM to"
|
||||
);
|
||||
|
||||
equal(
|
||||
$(targets[1]).text(), "test",
|
||||
"it fills up the composer with the right user to start the PM to"
|
||||
);
|
||||
|
||||
equal(
|
||||
$(targets[2]).text(), "Group",
|
||||
"it fills up the composer with the right group to start the PM to"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -118,6 +118,7 @@ export default function() {
|
|||
this.get("/t/280.json", () => response(fixturesByUrl['/t/280/1.json']));
|
||||
this.get("/t/28830.json", () => response(fixturesByUrl['/t/28830/1.json']));
|
||||
this.get("/t/9.json", () => response(fixturesByUrl['/t/9/1.json']));
|
||||
this.get("/t/12.json", () => response(fixturesByUrl['/t/12/1.json']));
|
||||
|
||||
this.get("/t/id_for/:slug", () => {
|
||||
return response({id: 280, slug: "internationalization-localization", url: "/t/internationalization-localization/280"});
|
||||
|
|
Loading…
Reference in New Issue
Block a user