diff --git a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee index 0ab23151d..c7d2002e6 100644 --- a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee +++ b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee @@ -117,7 +117,7 @@ class App.UiElement.ticket_perform_action element = @placeholder(item, attribute, params, groups, elements) @rebuildAttributeSelectors(item, element, groupAndAttribute, elements, meta, attribute) item.append(element) - + @disableRemoveForOneAttribute(item) item @@ -348,20 +348,38 @@ class App.UiElement.ticket_perform_action if !_.isArray(meta.recipient) meta.recipient = [meta.recipient] - column_select_options = [] + columnSelectOptions = [] for key, value of options selected = undefined for recipient in meta.recipient if key is recipient selected = true - column_select_options.push({ value: key, name: App.i18n.translateInline(value), selected: selected }) + columnSelectOptions.push({ value: key, name: App.i18n.translateInline(value), selected: selected }) - column_select = new App.ColumnSelect + columnSelectRecipientUserOptions = [] + for user in App.User.all() + key = "userid_#{user.id}" + selected = undefined + for recipient in meta.recipient + if key is recipient + selected = true + columnSelectRecipientUserOptions.push({ value: key, name: "#{user.firstname} #{user.lastname}", selected: selected }) + + columnSelectRecipient = new App.ColumnSelect attribute: name: "#{name}::recipient" - options: column_select_options + options: [ + { + label: 'Variables', + group: columnSelectOptions + }, + { + label: 'User', + group: columnSelectRecipientUserOptions + }, + ] - selection = column_select.element() + selectionRecipient = columnSelectRecipient.element() notificationElement = $( App.view('generic/ticket_perform_action/notification')( attribute: attribute @@ -369,7 +387,7 @@ class App.UiElement.ticket_perform_action notificationType: notificationType meta: meta || {} )) - notificationElement.find('.js-recipient select').replaceWith(selection) + notificationElement.find('.js-recipient select').replaceWith(selectionRecipient) visibilitySelection = App.UiElement.select.render( name: "#{name}::internal" diff --git a/app/assets/javascripts/app/views/generic/column_select.jst.eco b/app/assets/javascripts/app/views/generic/column_select.jst.eco index 82a12872f..a5072fc3f 100644 --- a/app/assets/javascripts/app/views/generic/column_select.jst.eco +++ b/app/assets/javascripts/app/views/generic/column_select.jst.eco @@ -34,7 +34,7 @@
<% for option in @attribute.options: %> <% if option.group != undefined: %> -
<%= option.label %>
+
<%= @T(option.label) %>
<% for o in option.group: %>
<%= o.name %>
<% end %> @@ -43,4 +43,4 @@ <% end %> <% end %>
- \ No newline at end of file + diff --git a/app/assets/javascripts/app/views/generic/ticket_perform_action/notification.jst.eco b/app/assets/javascripts/app/views/generic/ticket_perform_action/notification.jst.eco index 82c99b5d9..4348ce1af 100644 --- a/app/assets/javascripts/app/views/generic/ticket_perform_action/notification.jst.eco +++ b/app/assets/javascripts/app/views/generic/ticket_perform_action/notification.jst.eco @@ -12,14 +12,6 @@ -
-
- -
-
- -
-
<% if @notificationType is 'email': %>
diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 0e165e21a..f2c8b3095 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -1340,6 +1340,13 @@ result User.group_access(group_id, 'full').sort_by(&:login).each do |user| recipients_raw.push(user.email) end + elsif recipient =~ /\Auserid_(\d+)\z/ + user = User.lookup(id: $1) + if !user + logger.warn "Can't find configured Trigger Email recipient User with ID '#{$1}'" + next + end + recipients_raw.push(user.email) else logger.error "Unknown email notification recipient '#{recipient}'" next @@ -1538,6 +1545,11 @@ result owner_id when 'ticket_agents' User.group_access(group_id, 'full').sort_by(&:login) + when /\Auserid_(\d+)\z/ + return $1 if User.exists?($1) + + logger.warn "Can't find configured Trigger SMS recipient User with ID '#{$1}'" + nil else logger.error "Unknown sms notification recipient '#{recipient}'" nil @@ -1548,6 +1560,7 @@ result Array(value['recipient']) .each_with_object([]) { |recipient_type, sum| sum.concat(Array(sms_recipients_by_type(recipient_type, article))) } .map { |user_or_id| User.lookup(id: user_or_id) } + .uniq(&:id) .select { |user| user.mobile.present? } end diff --git a/public/assets/tests/form_extended.js b/public/assets/tests/form_extended.js index badcce98e..8c652b0ce 100644 --- a/public/assets/tests/form_extended.js +++ b/public/assets/tests/form_extended.js @@ -727,7 +727,7 @@ test('form checks', function() { internal: 'false' }, }, - } + } new App.ControllerForm({ el: el, model: { diff --git a/spec/models/trigger/sms_spec.rb b/spec/models/trigger/sms_spec.rb index 86bdffc51..7fb9e2dce 100644 --- a/spec/models/trigger/sms_spec.rb +++ b/spec/models/trigger/sms_spec.rb @@ -61,5 +61,36 @@ RSpec.describe Trigger do expect(triggered_article.body).to match(time_in_zone.strftime('%d.%m.%y')) end end + + context 'recipients' do + + let(:recipient1) { create(:agent_user, mobile: '+37061010000', groups: [ticket_group]) } + let(:recipient2) { create(:agent_user, mobile: '+37061010001', groups: [ticket_group]) } + let(:recipient3) { create(:agent_user, mobile: '+37061010002', groups: [ticket_group]) } + + let(:ticket_group) { create(:group) } + + let(:ticket) do + ticket = create(:ticket, group: ticket_group, created_by_id: create(:agent_user).id) + Observer::Transaction.commit + ticket + end + + before do + create(:channel, area: 'Sms::Notification') + create(:trigger, + disable_notification: false, + perform: { + 'notification.sms': { + recipient: ['ticket_agents', "userid_#{recipient1.id}", "userid_#{recipient2.id}", "userid_#{recipient3.id}"], + body: 'Hello World!', + } + }) + end + + it 'contains no duplicates' do + expect(ticket.articles.last.preferences['sms_recipients'].sort).to eq([recipient1.mobile, recipient2.mobile, recipient3.mobile].sort) + end + end end end diff --git a/spec/models/trigger_spec.rb b/spec/models/trigger_spec.rb index f3b075347..5f01c9823 100644 --- a/spec/models/trigger_spec.rb +++ b/spec/models/trigger_spec.rb @@ -6,6 +6,35 @@ RSpec.describe Trigger, type: :model do it_behaves_like 'ApplicationModel', can_assets: { selectors: %i[condition perform] } + describe 'validation' do + + let(:condition) do + { 'ticket.action' => { 'operator' => 'is', 'value' => 'create' } } + end + let(:perform) do + { 'ticket.title' => { 'value'=>'triggered' } } + end + + context 'notification.email' do + context 'missing recipient' do + + let(:perform) do + { + 'notification.email' => { + 'subject' => 'Hello', + 'body' => 'World!' + } + } + end + + it 'raises an error' do + expect { trigger.save! }.to raise_error(Exceptions::UnprocessableEntity, 'Invalid perform notification.email, recipient is missing!') + end + end + end + + end + describe 'Send-email triggers' do before do described_class.destroy_all # Default DB state includes three sample triggers @@ -87,6 +116,57 @@ RSpec.describe Trigger, type: :model do ) end end + + context 'notification.email recipient' do + let!(:ticket) { create(:ticket) } + let!(:recipient1) { create(:user, email: 'test1@zammad-test.com') } + let!(:recipient2) { create(:user, email: 'test2@zammad-test.com') } + let!(:recipient3) { create(:user, email: 'test3@zammad-test.com') } + + let(:perform) do + { + 'notification.email' => { + 'recipient' => recipient, + 'subject' => 'Hello', + 'body' => 'World!' + } + } + end + + before { Observer::Transaction.commit } + + context 'mix of recipient group keyword and single recipient users' do + let(:recipient) { [ 'ticket_customer', "userid_#{recipient1.id}", "userid_#{recipient2.id}", "userid_#{recipient3.id}" ] } + + it 'contains all recipients' do + expect(ticket.articles.last.to).to eq("#{ticket.customer.email}, #{recipient1.email}, #{recipient2.email}, #{recipient3.email}") + end + + context 'duplicate recipient' do + let(:recipient) { [ 'ticket_customer', "userid_#{ticket.customer.id}" ] } + + it 'contains only one recipient' do + expect(ticket.articles.last.to).to eq(ticket.customer.email.to_s) + end + end + end + + context 'list of single users only' do + let(:recipient) { [ "userid_#{recipient1.id}", "userid_#{recipient2.id}", "userid_#{recipient3.id}" ] } + + it 'contains all recipients' do + expect(ticket.articles.last.to).to eq("#{recipient1.email}, #{recipient2.email}, #{recipient3.email}") + end + end + + context 'recipient group keyword only' do + let(:recipient) { 'ticket_customer' } + + it 'contains matching recipient' do + expect(ticket.articles.last.to).to eq(ticket.customer.email.to_s) + end + end + end end context 'for condition "ticket updated"' do