Fixes #2485: Add attachment via Trigger and scheduler if wanted by admin

This commit is contained in:
Bola Ahmed Buari 2021-08-16 13:34:05 +02:00
parent 0b394f6baf
commit cc2c5678f0
8 changed files with 308 additions and 21 deletions

View file

@ -455,7 +455,17 @@ class App.UiElement.ticket_perform_action
translate: true
)
includeAttachmentsCheckbox = App.UiElement.select.render(
name: "#{name}::include_attachments"
multiple: false
null: false
options: { true: 'Yes', false: 'No' }
value: meta.include_attachments || 'false'
translate: true
)
notificationElement.find('.js-internal').html(visibilitySelection)
notificationElement.find('.js-include_attachments').html(includeAttachmentsCheckbox)
notificationElement.find('.js-body div[contenteditable="true"]').ce(
mode: 'richtext'

View file

@ -1,6 +1,6 @@
<div class="<%= @attribute.class %> checkbox checkbox--list">
<% for row in @attribute.options: %>
<label class="checkbox-replacement<%= ' is-disabled' if row.disabled %>">
<label class="checkbox-replacement<%= ' is-disabled' if row.disabled %> <%= row.class %>">
<input type="checkbox" value="<%= row.value %>" name="<%= @attribute.name %>" <%= row.checked %> <%= row.disabled %> <% if @attribute.disabled: %> disabled<% end %>>
<%- @Icon('checkbox', 'icon-unchecked') %>
<%- @Icon('checkbox-checked', 'icon-checked') %>

View file

@ -19,6 +19,12 @@
</div>
<div class="controls js-subject"><input type="text" name="<%= @name %>::subject" value="<%= @meta.subject %>" style="width: 100%;" placeholder="<%- @T('Subject') %>" class="form-control"></div>
</div>
<div class="form-group">
<div class="formGroup-label">
<label><%- @T('Include attachments of the article?') %></label>
</div>
<div class="js-include_attachments"></div>
</div>
<% end %>
<div class="form-group">
<div class="formGroup-label">

View file

@ -1755,6 +1755,11 @@ result
end
original_article = objects[:article]
if ActiveModel::Type::Boolean.new.cast(value['include_attachments']) == true && original_article&.attachments.present?
original_article.clone_attachments('Ticket::Article', message.id, only_attached_attachments: true)
end
if original_article&.should_clone_inline_attachments? # rubocop:disable Style/GuardClause
original_article.clone_attachments('Ticket::Article', message.id, only_inline_attachments: true)
original_article.should_clone_inline_attachments = false # cancel the temporary flag after cloning

View file

@ -413,7 +413,8 @@ test('form checks', function() {
recipient: 'ticket_customer',
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false'
internal: 'false',
include_attachments: 'false',
},
},
}
@ -486,7 +487,8 @@ test('form checks', function() {
recipient: 'ticket_customer',
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false'
internal: 'false',
include_attachments: 'false',
},
},
}
@ -548,6 +550,7 @@ test('form checks', function() {
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false',
include_attachments: 'false',
},
},
}
@ -660,7 +663,8 @@ test('form checks', function() {
recipient: 'ticket_owner',
subject: 'some subject',
body: 'lala',
internal: 'false'
internal: 'false',
include_attachments: 'false',
},
},
}
@ -681,7 +685,8 @@ test('form checks', function() {
recipient: 'ticket_customer',
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false'
internal: 'false',
include_attachments: 'false',
},
},
}
@ -711,6 +716,7 @@ test('form checks', function() {
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false',
include_attachments: 'false',
},
},
}
@ -730,7 +736,8 @@ test('form checks', function() {
recipient: 'ticket_customer',
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false'
internal: 'false',
include_attachments: 'true',
},
},
}
@ -758,7 +765,8 @@ test('form checks', function() {
recipient: 'ticket_customer',
subject: 'some subject',
body: "some<br>\nbody",
internal: 'false'
internal: 'false',
include_attachments: 'true',
},
},
}

View file

@ -51,7 +51,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: ['ticket_owner', 'ticket_customer'],
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
},
ticket_perform_action3: {
@ -103,7 +104,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: ['ticket_owner', 'ticket_customer'],
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -139,7 +141,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: ['ticket_owner', 'ticket_customer'],
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -153,7 +156,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_owner',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.state_id': {
value: '3'
@ -177,7 +181,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_customer',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -191,7 +196,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_owner',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.state_id': {
value: '3'
@ -215,7 +221,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'true',
recipient: 'ticket_customer',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -229,7 +236,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_owner',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.state_id': {
value: '3'
@ -262,7 +270,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'true',
recipient: 'ticket_customer',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -276,7 +285,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_owner',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.pending_time': {
operator: 'static',
@ -314,7 +324,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'true',
recipient: 'ticket_customer',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.priority_id': {
value: '2'
@ -328,7 +339,8 @@ test( "ticket_perform_action check", function(assert) {
body: 'some body',
internal: 'false',
recipient: 'ticket_owner',
subject: 'some subject'
subject: 'some subject',
include_attachments: 'false',
},
'ticket.pending_time': {
operator: 'relative',
@ -354,7 +366,8 @@ test( "ticket_perform_action backwards check after issue #2782", function() {
'notification.email': {
body: 'some body',
recipient: ['ticket_owner', 'ticket_customer'],
subject: 'some subject'
subject: 'some subject',
include_attachments: 'true',
},
},
}
@ -382,7 +395,8 @@ test( "ticket_perform_action backwards check after issue #2782", function() {
body: 'some body',
internal: 'false',
recipient: ['ticket_owner', 'ticket_customer'],
subject: 'some subject'
subject: 'some subject',
include_attachments: 'true',
},
}
}

View file

@ -520,6 +520,117 @@ RSpec.describe Ticket, type: :model do
include_examples 'verify log visibility status'
end
shared_examples 'add a new article' do
it 'adds a new article' do
expect { ticket.perform_changes(performable, 'trigger', ticket, user) }
.to change { ticket.articles.count }.by(1)
end
end
shared_examples 'add attachment to new article' do
include_examples 'add a new article'
it 'adds attachment to the new article' do
ticket.perform_changes(performable, 'trigger', ticket, user)
article = ticket.articles.last
expect(article.type.name).to eq('email')
expect(article.sender.name).to eq('System')
expect(article.attachments.count).to eq(1)
expect(article.attachments[0].filename).to eq('some_file.pdf')
expect(article.attachments[0].preferences['Content-ID']).to eq('image/pdf@01CAB192.K8H512Y9')
end
end
shared_examples 'does not add attachment to new article' do
include_examples 'add a new article'
it 'does not add attachment to the new article' do
ticket.perform_changes(performable, 'trigger', ticket, user)
article = ticket.articles.last
expect(article.type.name).to eq('email')
expect(article.sender.name).to eq('System')
expect(article.attachments.count).to eq(0)
end
end
context 'dispatching email with include attachment present' do
let(:notification_type) { :email }
let(:additional_options) do
{
notification_key => {
include_attachments: 'true'
}
}
end
context 'when ticket has an attachment' do
before do
UserInfo.current_user_id = 1
ticket_article = create(:ticket_article, ticket: ticket)
Store.add(
object: 'Ticket::Article',
o_id: ticket_article.id,
data: 'dGVzdCAxMjM=',
filename: 'some_file.pdf',
preferences: {
'Content-Type': 'image/pdf',
'Content-ID': 'image/pdf@01CAB192.K8H512Y9',
},
created_by_id: 1,
)
end
include_examples 'add attachment to new article'
end
context 'when ticket does not have an attachment' do
include_examples 'does not add attachment to new article'
end
end
context 'dispatching email with include attachment not present' do
let(:notification_type) { :email }
let(:additional_options) do
{
notification_key => {
include_attachments: 'false'
}
}
end
context 'when ticket has an attachment' do
before do
UserInfo.current_user_id = 1
ticket_article = create(:ticket_article, ticket: ticket)
Store.add(
object: 'Ticket::Article',
o_id: ticket_article.id,
data: 'dGVzdCAxMjM=',
filename: 'some_file.pdf',
preferences: {
'Content-Type': 'image/pdf',
'Content-ID': 'image/pdf@01CAB192.K8H512Y9',
},
created_by_id: 1,
)
end
include_examples 'does not add attachment to new article'
end
context 'when ticket does not have an attachment' do
include_examples 'does not add attachment to new article'
end
end
context 'dispatching SMS' do
let(:notification_type) { :sms }

View file

@ -55,6 +55,135 @@ RSpec.describe Trigger, type: :model do
}
end
shared_examples 'include ticket attachment' do
context 'notification.email include_attachments' do
let(:perform) do
{
'notification.email' => {
'recipient' => 'ticket_customer',
'subject' => 'Example subject',
'body' => 'Example body',
}
}.deep_merge(additional_options).deep_stringify_keys
end
let(:ticket) { create(:ticket) }
shared_examples 'add a new article' do
it 'adds a new article' do
expect { TransactionDispatcher.commit }
.to change(ticket.articles, :count).by(1)
end
end
shared_examples 'add attachment to new article' do
include_examples 'add a new article'
it 'adds attachment to the new article' do
ticket && trigger
TransactionDispatcher.commit
article = ticket.articles.last
expect(article.type.name).to eq('email')
expect(article.sender.name).to eq('System')
expect(article.attachments.count).to eq(1)
expect(article.attachments[0].filename).to eq('some_file.pdf')
expect(article.attachments[0].preferences['Content-ID']).to eq('image/pdf@01CAB192.K8H512Y9')
end
end
shared_examples 'does not add attachment to new article' do
include_examples 'add a new article'
it 'does not add attachment to the new article' do
ticket && trigger
TransactionDispatcher.commit
article = ticket.articles.last
expect(article.type.name).to eq('email')
expect(article.sender.name).to eq('System')
expect(article.attachments.count).to eq(0)
end
end
context 'with include attachment present' do
let(:additional_options) do
{
'notification.email' => {
include_attachments: 'true'
}
}
end
context 'when ticket has an attachment' do
before do
UserInfo.current_user_id = 1
ticket_article = create(:ticket_article, ticket: ticket)
Store.add(
object: 'Ticket::Article',
o_id: ticket_article.id,
data: 'dGVzdCAxMjM=',
filename: 'some_file.pdf',
preferences: {
'Content-Type': 'image/pdf',
'Content-ID': 'image/pdf@01CAB192.K8H512Y9',
},
created_by_id: 1,
)
end
include_examples 'add attachment to new article'
end
context 'when ticket does not have an attachment' do
include_examples 'does not add attachment to new article'
end
end
context 'with include attachment not present' do
let(:additional_options) do
{
'notification.email' => {
include_attachments: 'false'
}
}
end
context 'when ticket has an attachment' do
before do
UserInfo.current_user_id = 1
ticket_article = create(:ticket_article, ticket: ticket)
Store.add(
object: 'Ticket::Article',
o_id: ticket_article.id,
data: 'dGVzdCAxMjM=',
filename: 'some_file.pdf',
preferences: {
'Content-Type': 'image/pdf',
'Content-ID': 'image/pdf@01CAB192.K8H512Y9',
},
created_by_id: 1,
)
end
include_examples 'does not add attachment to new article'
end
context 'when ticket does not have an attachment' do
include_examples 'does not add attachment to new article'
end
end
end
end
context 'for condition "ticket created"' do
let(:condition) do
{ 'ticket.action' => { 'operator' => 'is', 'value' => 'create' } }
@ -417,6 +546,8 @@ RSpec.describe Trigger, type: :model do
end
end
end
include_examples 'include ticket attachment'
end
context 'for condition "ticket updated"' do
@ -575,6 +706,8 @@ RSpec.describe Trigger, type: :model do
expect(Ticket::Article.where(ticket: ticket).last.to).not_to eq(system_address.email)
end
end
include_examples 'include ticket attachment'
end
end