Added generic use of all X-headers. Improved ui for postmaster filter.
This commit is contained in:
parent
eb48ac0e4f
commit
d436872bc7
4 changed files with 187 additions and 54 deletions
|
@ -258,25 +258,29 @@ class App.ControllerForm extends App.Controller
|
|||
# postmaster_match
|
||||
else if attribute.tag is 'postmaster_match'
|
||||
addItem = (key, displayName, el, defaultValue = '') =>
|
||||
itemInput = $("<div>#{ App.i18n.translateInline(displayName) }: <input name=\"#{ key }\" type=\"input\" value=\"#{ defaultValue }\" class=\"form-control\" required/><a href=\"#\" class=\"glyphicon glyphicon-minus remove\"></a></div>")
|
||||
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue }
|
||||
itemInput = $( @formGenItem( add ).append('<a href=\"#\" class=\"glyphicon glyphicon-minus remove\"></a>' ) )
|
||||
|
||||
# remove on click
|
||||
itemInput.find('.remove').bind('click', (e) ->
|
||||
e.preventDefault()
|
||||
key = $(e.target).prev().attr('name')
|
||||
key = $(e.target).parent().find('select, input').attr('name')
|
||||
return if !key
|
||||
$(e.target).parent().parent().parent().find('.addSelection select option[value="' + key + '"]').show()
|
||||
$(e.target).parent().parent().parent().find('.list [name="' + key + '"]').parent().remove()
|
||||
$(e.target).parent().parent().parent().find('.addSelection select option[value="' + key + '"]').prop('disabled', false)
|
||||
$(e.target).parent().parent().parent().find('.list [name="' + key + '"]').parent().parent().remove()
|
||||
)
|
||||
|
||||
# add new item
|
||||
el.parent().parent().parent().find('.list').append(itemInput)
|
||||
el.parent().parent().parent().find('.addSelection select').val('')
|
||||
el.parent().parent().parent().find('.addSelection select option[value="' + key + '"]').prop('disabled', true)
|
||||
el.parent().parent().parent().find('.addSelection select option[value="' + key + '"]').hide()
|
||||
|
||||
# scaffold of match elements
|
||||
item = $('
|
||||
<div class="postmaster_match" style="margin-left: 40px;">
|
||||
<div class="postmaster_match">
|
||||
<hr>
|
||||
<div class="list"></div>
|
||||
<hr>
|
||||
<div>
|
||||
|
@ -408,7 +412,7 @@ class App.ControllerForm extends App.Controller
|
|||
]
|
||||
for listItem in loopData
|
||||
listItem.value = "#{ attribute.name }::#{listItem.value}"
|
||||
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true }
|
||||
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
|
||||
item.find('.addSelection').append( @formGenItem( add ) )
|
||||
|
||||
# bind add click
|
||||
|
@ -432,25 +436,39 @@ class App.ControllerForm extends App.Controller
|
|||
# postmaster_set
|
||||
else if attribute.tag is 'postmaster_set'
|
||||
addItem = (key, displayName, el, defaultValue = '') =>
|
||||
itemInput = $("<div>#{ App.i18n.translateInline(displayName) }: <input name=\"#{ key }\" type=\"input\" value=\"#{ defaultValue }\" class=\"form-control\"/><a href=\"#\" class=\"glyphicon glyphicon-minus remove\"></a></div>")
|
||||
collection = undefined
|
||||
for listItem in loopData
|
||||
if listItem.value is key
|
||||
collection = listItem
|
||||
if collection.relation
|
||||
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, relation: collection.relation, translate: true, default: defaultValue }
|
||||
else if collection.options
|
||||
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, options: collection.options, translate: true, default: defaultValue }
|
||||
else
|
||||
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue }
|
||||
itemInput = $( @formGenItem( add ).append('<a href=\"#\" class=\"glyphicon glyphicon-minus remove\"></a>' ) )
|
||||
|
||||
# remove on click
|
||||
itemInput.find('.remove').bind('click', (e) ->
|
||||
e.preventDefault()
|
||||
key = $(e.target).prev().attr('name')
|
||||
key = $(e.target).parent().find('select, input').attr('name')
|
||||
return if !key
|
||||
$(e.target).parent().parent().parent().find('.addSelection select option[value="' + key + '"]').show()
|
||||
$(e.target).parent().parent().parent().find('.list [name="' + key + '"]').parent().remove()
|
||||
$(e.target).parent().parent().parent().find('.addSelection select option[value="' + key + '"]').prop('disabled', false)
|
||||
$(e.target).parent().parent().parent().find('.list [name="' + key + '"]').parent().parent().remove()
|
||||
)
|
||||
|
||||
# add new item
|
||||
console.log(1111222, key, el, el.parent().parent().parent().find('.addSelection select'))
|
||||
el.parent().parent().parent().find('.list').append(itemInput)
|
||||
el.parent().parent().parent().find('.addSelection select').val('')
|
||||
el.parent().parent().parent().find('.addSelection select option[value="' + key + '"]').prop('disabled', true)
|
||||
el.parent().parent().parent().find('.addSelection select option[value="' + key + '"]').hide()
|
||||
|
||||
# scaffold of perform elements
|
||||
item = $('
|
||||
<div class="perform_set" style="margin-left: 40px;">
|
||||
<div class="perform_set">
|
||||
<hr>
|
||||
<div class="list"></div>
|
||||
<hr>
|
||||
<div>
|
||||
|
@ -463,20 +481,23 @@ class App.ControllerForm extends App.Controller
|
|||
# select shown attributes
|
||||
loopData = [
|
||||
{
|
||||
value: 'x-zammad-ticket-priority'
|
||||
value: 'x-zammad-ticket-ticket_priority_id'
|
||||
name: 'Ticket Priority'
|
||||
relation: 'TicketPriority'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-ticket-state'
|
||||
value: 'x-zammad-ticket-ticket_state_id'
|
||||
name: 'Ticket State'
|
||||
relation: 'TicketState'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-ticket-customer'
|
||||
name: 'Ticket Customer'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-ticket-group'
|
||||
value: 'x-zammad-ticket-group_id'
|
||||
name: 'Ticket Group'
|
||||
relation: 'Group'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-ticket-owner'
|
||||
|
@ -488,16 +509,18 @@ class App.ControllerForm extends App.Controller
|
|||
disable: true
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-article-visibility'
|
||||
name: 'Article Visibility'
|
||||
value: 'x-zammad-article-ticket_article_internal'
|
||||
name: 'Article Internal'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-article-type'
|
||||
value: 'x-zammad-article-ticket_article_type_id'
|
||||
name: 'Article Type'
|
||||
relation: 'TicketArticleType'
|
||||
},
|
||||
{
|
||||
value: 'x-zammad-article-sender'
|
||||
value: 'x-zammad-article-ticket_article_sender_id'
|
||||
name: 'Article Sender'
|
||||
relation: 'TicketArticleSender'
|
||||
},
|
||||
{
|
||||
value: ''
|
||||
|
@ -507,11 +530,12 @@ class App.ControllerForm extends App.Controller
|
|||
{
|
||||
value: 'x-zammad-ignore'
|
||||
name: 'Ignore Message'
|
||||
options: { true: 'Yes', false: 'No'}
|
||||
},
|
||||
]
|
||||
for listItem in loopData
|
||||
listItem.value = "#{ attribute.name }::#{listItem.value}"
|
||||
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true }
|
||||
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
|
||||
item.find('.addSelection').append( @formGenItem( add ) )
|
||||
|
||||
item.find('.add').bind('click', (e) ->
|
||||
|
|
|
@ -371,25 +371,18 @@ class Channel::EmailParser
|
|||
if !ticket
|
||||
|
||||
# set attributes
|
||||
ticket_attributes = {
|
||||
ticket = Ticket.new(
|
||||
:group_id => channel[:group_id] || 1,
|
||||
:customer_id => user.id,
|
||||
:title => mail[:subject] || '',
|
||||
:ticket_state_id => Ticket::State.where( :name => 'new' ).first.id,
|
||||
:ticket_priority_id => Ticket::Priority.where( :name => '2 normal' ).first.id,
|
||||
}
|
||||
)
|
||||
|
||||
# x-headers lookup
|
||||
map = [
|
||||
[ 'x-zammad-ticket-group', Group, 'group_id', 'name' ],
|
||||
[ 'x-zammad-ticket-state', Ticket::State, 'ticket_state_id', 'name' ],
|
||||
[ 'x-zammad-ticket-priority', Ticket::Priority, 'ticket_priority_id', 'name' ],
|
||||
[ 'x-zammad-ticket-owner', User, 'owner_id', 'login' ],
|
||||
]
|
||||
object_lookup( ticket_attributes, map, mail )
|
||||
object_lookup( ticket, 'ticket', mail )
|
||||
|
||||
# create ticket
|
||||
ticket = Ticket.create( ticket_attributes )
|
||||
ticket.save
|
||||
end
|
||||
|
||||
# import mail
|
||||
|
@ -399,7 +392,7 @@ class Channel::EmailParser
|
|||
if mail[ 'X-Zammad-Article-Visibility'.to_sym ] && mail[ 'X-Zammad-Article-Visibility'.to_sym ] == 'internal'
|
||||
internal = true
|
||||
end
|
||||
article_attributes = {
|
||||
article = Ticket::Article.new(
|
||||
:ticket_id => ticket.id,
|
||||
:ticket_article_type_id => Ticket::Article::Type.where( :name => 'email' ).first.id,
|
||||
:ticket_article_sender_id => Ticket::Article::Sender.where( :name => 'Customer' ).first.id,
|
||||
|
@ -410,17 +403,13 @@ class Channel::EmailParser
|
|||
:subject => mail[:subject],
|
||||
:message_id => mail[:message_id],
|
||||
:internal => internal,
|
||||
}
|
||||
)
|
||||
|
||||
# x-headers lookup
|
||||
map = [
|
||||
[ 'x-zammad-article-type', Ticket::Article::Type, 'ticket_article_type_id', 'name' ],
|
||||
[ 'x-zammad-article-sender', Ticket::Article::Sender, 'ticket_article_sender_id', 'name' ],
|
||||
]
|
||||
object_lookup( article_attributes, map, mail )
|
||||
object_lookup( article, 'article', mail )
|
||||
|
||||
# create article
|
||||
article = Ticket::Article.create(article_attributes)
|
||||
article.save
|
||||
|
||||
# store mail plain
|
||||
Store.add(
|
||||
|
@ -467,15 +456,51 @@ class Channel::EmailParser
|
|||
return ticket, article, user
|
||||
end
|
||||
|
||||
def object_lookup( attributes, map, mail )
|
||||
map.each { |item|
|
||||
if mail[ item[0].to_sym ]
|
||||
new_object = item[1].where( "lower(#{item[3]}) = ?", mail[ item[0].to_sym ].downcase ).first
|
||||
if new_object
|
||||
attributes[ item[2].to_sym ] = new_object.id
|
||||
def object_lookup( item_object, header_name, mail )
|
||||
|
||||
# loop all x-zammad-hedaer-* headers
|
||||
item_object.attributes.each{|key,value|
|
||||
|
||||
# ignore read only attributes
|
||||
next if key == 'updated_at'
|
||||
next if key == 'created_at'
|
||||
next if key == 'updated_by_id'
|
||||
next if key == 'created_by_id'
|
||||
|
||||
# check if id exists
|
||||
key_short = key[ key.length-3 , key.length ]
|
||||
if key_short == '_id'
|
||||
key_short = key[ 0, key.length-3 ]
|
||||
header = "x-zammad-#{header_name}-#{key_short}"
|
||||
if mail[ header.to_sym ]
|
||||
puts "NOTICE: header #{header} found #{mail[ header.to_sym ]}"
|
||||
item_object.class.reflect_on_all_associations.map { |assoc|
|
||||
if assoc.name.to_s == key_short
|
||||
puts "NOTICE: ASSOC found #{assoc.class_name} lookup #{mail[ header.to_sym ]}"
|
||||
item = assoc.class_name.constantize
|
||||
|
||||
if item.respond_to?(:name)
|
||||
if item.lookup( :name => mail[ header.to_sym ] )
|
||||
item_object[key] = item.lookup( :name => mail[ header.to_sym ] ).id
|
||||
end
|
||||
elsif item.respond_to?(:login)
|
||||
if item.lookup( :login => mail[ header.to_sym ] )
|
||||
item_object[key] = item.lookup( :login => mail[ header.to_sym ] ).id
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# check if attribute exists
|
||||
header = "x-zammad-#{header_name}-#{key}"
|
||||
if mail[ header.to_sym ]
|
||||
puts "NOTICE: header #{header} found #{mail[ header.to_sym ]}"
|
||||
item_object[key] = mail[ header.to_sym ]
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def html2ascii(string)
|
||||
|
|
|
@ -376,6 +376,26 @@ test( "form postmaster filter", function() {
|
|||
// add match rule
|
||||
|
||||
// add set rule
|
||||
App.TicketPriority.refresh( [
|
||||
{
|
||||
id: 1,
|
||||
name: 'prio 1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'prio 2',
|
||||
},
|
||||
] )
|
||||
App.Group.refresh( [
|
||||
{
|
||||
id: 1,
|
||||
name: 'group 1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'group 2',
|
||||
},
|
||||
] )
|
||||
|
||||
$('#forms').append('<hr><h1>form postmaster filter</h1><form id="form5"></form>')
|
||||
var el = $('#form5')
|
||||
|
@ -386,8 +406,10 @@ test( "form postmaster filter", function() {
|
|||
subject: 'some subject',
|
||||
},
|
||||
set: {
|
||||
'x-zammad-ticket-priority': '3 high',
|
||||
'x-zammad-ticket-group': 'some group',
|
||||
'x-zammad-ticket-owner': 'owner',
|
||||
'x-zammad-ticket-customer': 'customer',
|
||||
'x-zammad-ticket-ticket_priority_id': 2,
|
||||
'x-zammad-ticket-group_id': 1,
|
||||
},
|
||||
}
|
||||
new App.ControllerForm({
|
||||
|
@ -411,12 +433,15 @@ test( "form postmaster filter", function() {
|
|||
subject: 'some subject',
|
||||
},
|
||||
set: {
|
||||
'x-zammad-ticket-priority': '3 high',
|
||||
'x-zammad-ticket-group': 'some group',
|
||||
'x-zammad-ticket-owner': 'owner',
|
||||
'x-zammad-ticket-customer': 'customer',
|
||||
'x-zammad-ticket-ticket_priority_id': "2",
|
||||
'x-zammad-ticket-group_id': "1",
|
||||
},
|
||||
};
|
||||
deepEqual( params, test_params, 'form param check' );
|
||||
el.find('[name="set::x-zammad-ticket-priority"]').next().click()
|
||||
el.find('[name="set::x-zammad-ticket-ticket_priority_id"]').parent().next().click()
|
||||
el.find('[name="set::x-zammad-ticket-customer"]').parent().next().click()
|
||||
App.Delay.set( function() {
|
||||
test( "form param check after remove click", function() {
|
||||
params = App.ControllerForm.params( el )
|
||||
|
@ -428,7 +453,8 @@ test( "form postmaster filter", function() {
|
|||
subject: 'some subject',
|
||||
},
|
||||
set: {
|
||||
'x-zammad-ticket-group': 'some group',
|
||||
'x-zammad-ticket-owner': 'owner',
|
||||
'x-zammad-ticket-group_id': "1",
|
||||
},
|
||||
};
|
||||
deepEqual( params, test_params, 'form param check' );
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# encoding: utf-8
|
||||
require 'test_helper'
|
||||
|
||||
|
||||
class EmailProcessTest < ActiveSupport::TestCase
|
||||
test 'process' do
|
||||
test 'process trusted' do
|
||||
files = [
|
||||
{
|
||||
:data => 'From: me@example.com
|
||||
|
@ -25,9 +25,10 @@ Some Text',
|
|||
:data => 'From: me@example.com
|
||||
To: customer@example.com
|
||||
Subject: some subject
|
||||
X-Zammad-Ticket-Priority: 3 high
|
||||
X-Zammad-Article-Sender: system
|
||||
x-Zammad-Article-Type: phone
|
||||
X-Zammad-Ticket-Ticket_Priority: 3 high
|
||||
X-Zammad-Article-Ticket_Article_Sender: System
|
||||
x-Zammad-Article-Ticket_Article_Type: phone
|
||||
x-Zammad-Article-Internal: true
|
||||
|
||||
Some Text',
|
||||
:success => true,
|
||||
|
@ -39,6 +40,7 @@ Some Text',
|
|||
1 => {
|
||||
:ticket_article_sender => 'System',
|
||||
:ticket_article_type => 'phone',
|
||||
:internal => true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -58,6 +60,7 @@ Some Textäöü",
|
|||
:body => 'Some Textäöü',
|
||||
:ticket_article_sender => 'Customer',
|
||||
:ticket_article_type => 'email',
|
||||
:internal => false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -77,6 +80,7 @@ Some Textäöü".encode("ISO-8859-1"),
|
|||
:body => 'Some Textäöü',
|
||||
:ticket_article_sender => 'Customer',
|
||||
:ticket_article_type => 'email',
|
||||
:internal => false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -168,7 +172,61 @@ Some Text",
|
|||
if result[level].send(key).respond_to?('name')
|
||||
assert_equal( result[level].send(key).name, value.to_s)
|
||||
else
|
||||
assert_equal( result[level].send(key), value.to_s)
|
||||
assert_equal( result[level].send(key), value)
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
elsif !file[:success] && result == true
|
||||
assert( true )
|
||||
elsif !file[:success] && result[1]
|
||||
assert( false, 'ticket should not be created' )
|
||||
else
|
||||
assert( false, 'UNKNOWN!' )
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
test 'process not trusted' do
|
||||
files = [
|
||||
{
|
||||
:data => 'From: me@example.com
|
||||
To: customer@example.com
|
||||
Subject: some subject
|
||||
X-Zammad-Ticket-Ticket_Priority: 3 high
|
||||
X-Zammad-Article-Ticket_Article_Sender: System
|
||||
x-Zammad-Article-Ticket_Article_Type: phone
|
||||
x-Zammad-Article-Internal: true
|
||||
|
||||
Some Text',
|
||||
:success => true,
|
||||
:result => {
|
||||
0 => {
|
||||
:ticket_priority => '2 normal',
|
||||
:title => 'some subject',
|
||||
},
|
||||
1 => {
|
||||
:ticket_article_sender => 'Customer',
|
||||
:ticket_article_type => 'email',
|
||||
:internal => false,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
files.each { |file|
|
||||
parser = Channel::EmailParser.new
|
||||
result = parser.process( { :trusted => false }, file[:data] )
|
||||
if file[:success] && result[1]
|
||||
assert( true )
|
||||
if file[:result]
|
||||
[ 0, 1, 2 ].each { |level|
|
||||
if file[:result][level]
|
||||
file[:result][level].each { |key, value|
|
||||
if result[level].send(key).respond_to?('name')
|
||||
assert_equal( result[level].send(key).name, value.to_s)
|
||||
else
|
||||
assert_equal( result[level].send(key), value)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue