feat: Ability to specify a subject line for outbound emails (#3168)
This commit is contained in:
parent
2f2d2b4f73
commit
46867e89cb
6 changed files with 83 additions and 14 deletions
|
@ -155,6 +155,11 @@
|
|||
"LABEL": "Inbox",
|
||||
"ERROR": "Select an inbox"
|
||||
},
|
||||
"SUBJECT": {
|
||||
"LABEL": "Subject",
|
||||
"PLACEHOLDER": "Subject",
|
||||
"ERROR": "Subject can't be empty"
|
||||
},
|
||||
"MESSAGE": {
|
||||
"LABEL": "Message",
|
||||
"PLACEHOLDER": "Write your message here",
|
||||
|
|
|
@ -41,6 +41,22 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="isAnEmailInbox">
|
||||
<div class="columns">
|
||||
<label :class="{ error: $v.message.$error }">
|
||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
|
||||
<input
|
||||
v-model="subject"
|
||||
type="text"
|
||||
:placeholder="$t('NEW_CONVERSATION.FORM.SUBJECT.PLACEHOLDER')"
|
||||
@input="$v.message.$touch"
|
||||
/>
|
||||
<span v-if="$v.message.$error" class="message">
|
||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns">
|
||||
<label :class="{ error: $v.message.$error }">
|
||||
|
@ -75,6 +91,7 @@ import { mapGetters } from 'vuex';
|
|||
import Thumbnail from 'dashboard/components/widgets/Thumbnail';
|
||||
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
||||
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
|
||||
|
@ -96,11 +113,15 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
name: '',
|
||||
subject: '',
|
||||
message: '',
|
||||
selectedInbox: '',
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
subject: {
|
||||
required,
|
||||
},
|
||||
message: {
|
||||
required,
|
||||
},
|
||||
|
@ -119,6 +140,7 @@ export default {
|
|||
sourceId: this.targetInbox.source_id,
|
||||
contactId: this.contact.id,
|
||||
message: { content: this.message },
|
||||
mailSubject: this.subject,
|
||||
};
|
||||
},
|
||||
targetInbox: {
|
||||
|
@ -138,6 +160,12 @@ export default {
|
|||
inboxes() {
|
||||
return this.contact.contactableInboxes || [];
|
||||
},
|
||||
isAnEmailInbox() {
|
||||
return (
|
||||
this.selectedInbox &&
|
||||
this.selectedInbox.inbox.channel_type === INBOX_TYPES.EMAIL
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onCancel() {
|
||||
|
@ -154,7 +182,6 @@ export default {
|
|||
}
|
||||
try {
|
||||
const payload = this.getNewConversation;
|
||||
|
||||
await this.onSubmit(payload);
|
||||
this.onSuccess();
|
||||
this.showAlert(this.$t('NEW_CONVERSATION.FORM.SUCCESS_MESSAGE'));
|
||||
|
|
|
@ -24,12 +24,15 @@ export const actions = {
|
|||
commit(types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, {
|
||||
isCreating: true,
|
||||
});
|
||||
const { inboxId, message, contactId, sourceId } = params;
|
||||
const { inboxId, message, contactId, sourceId, mailSubject } = params;
|
||||
try {
|
||||
const { data } = await ConversationApi.create({
|
||||
inbox_id: inboxId,
|
||||
contact_id: contactId,
|
||||
source_id: sourceId,
|
||||
additional_attributes: {
|
||||
mail_subject: mailSubject,
|
||||
},
|
||||
message,
|
||||
});
|
||||
commit(types.default.ADD_CONTACT_CONVERSATION, {
|
||||
|
|
|
@ -44,7 +44,13 @@ describe('#actions', () => {
|
|||
axios.post.mockResolvedValue({ data: conversationList[0] });
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{ inboxId: 1, message: { content: 'hi' }, contactId: 4, sourceId: 5 }
|
||||
{
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
|
@ -65,7 +71,13 @@ describe('#actions', () => {
|
|||
await expect(
|
||||
actions.create(
|
||||
{ commit },
|
||||
{ inboxId: 1, message: { content: 'hi' }, contactId: 4, sourceId: 5 }
|
||||
{
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
|
|
|
@ -12,7 +12,6 @@ class ConversationReplyMailer < ApplicationMailer
|
|||
new_messages = @conversation.messages.chat.where('id >= ?', last_queued_id)
|
||||
@messages = recap_messages + new_messages
|
||||
@messages = @messages.select(&:email_reply_summarizable?)
|
||||
|
||||
mail({
|
||||
to: @contact&.email,
|
||||
from: from_email_with_name,
|
||||
|
@ -110,14 +109,15 @@ class ConversationReplyMailer < ApplicationMailer
|
|||
end
|
||||
|
||||
def mail_subject
|
||||
return "Re: #{incoming_mail_subject}" if incoming_mail_subject
|
||||
subject = @conversation.additional_attributes['mail_subject']
|
||||
return "[##{@conversation.display_id}] #{I18n.t('conversations.reply.email_subject')}" if subject.nil?
|
||||
|
||||
subject_line = I18n.t('conversations.reply.email_subject')
|
||||
"[##{@conversation.display_id}] #{subject_line}"
|
||||
end
|
||||
|
||||
def incoming_mail_subject
|
||||
@incoming_mail_subject ||= @conversation.additional_attributes['mail_subject']
|
||||
chat_count = @conversation.messages.chat.count
|
||||
if chat_count > 1
|
||||
"Re: #{subject}"
|
||||
else
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
def reply_email
|
||||
|
|
|
@ -25,6 +25,15 @@ RSpec.describe ConversationReplyMailer, type: :mailer do
|
|||
bcc_emails: 'agent_bcc1@example.com'
|
||||
})
|
||||
end
|
||||
let(:new_message) do
|
||||
create(:message,
|
||||
account: account,
|
||||
conversation: conversation,
|
||||
content_attributes: {
|
||||
cc_emails: 'agent_cc2@example.com',
|
||||
bcc_emails: 'agent_bcc2@example.com'
|
||||
})
|
||||
end
|
||||
let(:cc_message) do
|
||||
create(:message,
|
||||
account: account,
|
||||
|
@ -39,10 +48,17 @@ RSpec.describe ConversationReplyMailer, type: :mailer do
|
|||
let(:mail) { described_class.reply_with_summary(message.conversation, message.id).deliver_now }
|
||||
let(:cc_mail) { described_class.reply_with_summary(cc_message.conversation, message.id).deliver_now }
|
||||
|
||||
it 'renders the subject' do
|
||||
it 'renders the default subject' do
|
||||
expect(mail.subject).to eq("[##{message.conversation.display_id}] New messages on this conversation")
|
||||
end
|
||||
|
||||
it 'renders the subject in conversation as reply' do
|
||||
conversation.additional_attributes = { 'mail_subject': 'Mail Subject' }
|
||||
conversation.save
|
||||
new_message.save
|
||||
expect(mail.subject).to eq('Re: Mail Subject')
|
||||
end
|
||||
|
||||
it 'not have private notes' do
|
||||
# make the message private
|
||||
private_message.private = true
|
||||
|
@ -91,10 +107,16 @@ RSpec.describe ConversationReplyMailer, type: :mailer do
|
|||
message_2.save
|
||||
end
|
||||
|
||||
it 'renders the subject' do
|
||||
it 'renders the default subject' do
|
||||
expect(mail.subject).to eq("[##{message_2.conversation.display_id}] New messages on this conversation")
|
||||
end
|
||||
|
||||
it 'renders the subject in conversation' do
|
||||
conversation.additional_attributes = { 'mail_subject': 'Mail Subject' }
|
||||
conversation.save
|
||||
expect(mail.subject).to eq('Mail Subject')
|
||||
end
|
||||
|
||||
it 'not have private notes' do
|
||||
# make the message private
|
||||
private_message.private = true
|
||||
|
|
Loading…
Reference in a new issue