Added support for signature and different sender addresses.
This commit is contained in:
parent
6b9af49fa8
commit
7d23efda79
21 changed files with 643 additions and 132 deletions
4
Gemfile
4
Gemfile
|
@ -1,6 +1,6 @@
|
||||||
source 'http://rubygems.org'
|
source 'http://rubygems.org'
|
||||||
|
|
||||||
gem 'rails', '3.2.3'
|
gem 'rails', '3.2.8'
|
||||||
|
|
||||||
# Bundle edge Rails instead:
|
# Bundle edge Rails instead:
|
||||||
#gem 'rails', :git => 'git://github.com/rails/rails.git'
|
#gem 'rails', :git => 'git://github.com/rails/rails.git'
|
||||||
|
@ -47,7 +47,7 @@ gem 'simple-rss'
|
||||||
# gem 'therubyracer'
|
# gem 'therubyracer'
|
||||||
|
|
||||||
# e. g. for mysql you need to load mysql
|
# e. g. for mysql you need to load mysql
|
||||||
# gem 'mysql2'
|
gem 'mysql2'
|
||||||
|
|
||||||
# Use unicorn as the web server
|
# Use unicorn as the web server
|
||||||
# gem 'unicorn'
|
# gem 'unicorn'
|
||||||
|
|
|
@ -382,19 +382,11 @@ class App.ControllerForm extends App.Controller
|
||||||
|
|
||||||
# if active or if active doesn't exist
|
# if active or if active doesn't exist
|
||||||
if item.active || !( 'active' of item )
|
if item.active || !( 'active' of item )
|
||||||
name = '???'
|
name_new = '?'
|
||||||
if item.name
|
if item.displayName
|
||||||
name = item.name
|
name_new = item.displayName()
|
||||||
else if item.firstname
|
|
||||||
name = item.firstname
|
|
||||||
if item.lastname
|
|
||||||
if name
|
|
||||||
name = name + ' '
|
|
||||||
name = name + item.lastname
|
|
||||||
|
|
||||||
name_new = name
|
|
||||||
if attribute.translate
|
if attribute.translate
|
||||||
name_new = Ti(name)
|
name_new = Ti(name_new)
|
||||||
attribute.options.push {
|
attribute.options.push {
|
||||||
name: name_new,
|
name: name_new,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
|
|
|
@ -21,12 +21,14 @@ class App.ChannelEmail extends App.ControllerTabs
|
||||||
controller: App.ChannelEmailOutbound,
|
controller: App.ChannelEmailOutbound,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Sigantures',
|
name: 'Sigantures',
|
||||||
target: 'c-signature',
|
target: 'c-signature',
|
||||||
|
controller: App.ChannelEmailSignature,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Adresses',
|
name: 'Adresses',
|
||||||
target: 'c-address',
|
target: 'c-address',
|
||||||
|
controller: App.ChannelEmailAddress,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Filter',
|
name: 'Filter',
|
||||||
|
@ -42,6 +44,183 @@ class App.ChannelEmail extends App.ControllerTabs
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
|
class App.ChannelEmailAddress extends App.Controller
|
||||||
|
events:
|
||||||
|
'click [data-type=new]': 'new'
|
||||||
|
'click [data-type=edit]': 'edit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
App.EmailAddress.bind 'refresh change', @render
|
||||||
|
App.EmailAddress.fetch()
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
data = App.EmailAddress.all()
|
||||||
|
|
||||||
|
html = $('<div></div>')
|
||||||
|
|
||||||
|
table = @table(
|
||||||
|
model: App.EmailAddress,
|
||||||
|
objects: data,
|
||||||
|
)
|
||||||
|
|
||||||
|
html.append( table )
|
||||||
|
html.append( '<a data-type="new" class="btn">' + T('New') + '</a>' )
|
||||||
|
@html html
|
||||||
|
|
||||||
|
new: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
new App.ChannelEmailAddressEdit()
|
||||||
|
|
||||||
|
edit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
item = $(e.target).item( App.EmailAddress )
|
||||||
|
new App.ChannelEmailAddressEdit( object: item )
|
||||||
|
|
||||||
|
class App.ChannelEmailAddressEdit extends App.ControllerModal
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render(@object)
|
||||||
|
|
||||||
|
render: (data = {}) ->
|
||||||
|
if @object
|
||||||
|
@html App.view('generic/admin/edit')(
|
||||||
|
head: 'Email-Address'
|
||||||
|
)
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @el.find('#object_edit'),
|
||||||
|
model: App.EmailAddress,
|
||||||
|
params: @object,
|
||||||
|
autofocus: true,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@html App.view('generic/admin/new')(
|
||||||
|
head: 'Email-Address'
|
||||||
|
)
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @el.find('#object_new'),
|
||||||
|
model: App.EmailAddress,
|
||||||
|
autofocus: true,
|
||||||
|
)
|
||||||
|
@modalShow()
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
# get params
|
||||||
|
params = @formParam(e.target)
|
||||||
|
|
||||||
|
object = @object || new App.EmailAddress
|
||||||
|
object.load(params)
|
||||||
|
|
||||||
|
# validate form
|
||||||
|
errors = @form.validate( params )
|
||||||
|
|
||||||
|
# show errors in form
|
||||||
|
if errors
|
||||||
|
@log 'error new', errors
|
||||||
|
@formValidate( form: e.target, errors: errors )
|
||||||
|
return false
|
||||||
|
|
||||||
|
# save object
|
||||||
|
object.save(
|
||||||
|
success: =>
|
||||||
|
@modalHide()
|
||||||
|
error: =>
|
||||||
|
@log 'errors'
|
||||||
|
@modalHide()
|
||||||
|
)
|
||||||
|
|
||||||
|
class App.ChannelEmailSignature extends App.Controller
|
||||||
|
events:
|
||||||
|
'click [data-type=new]': 'new'
|
||||||
|
'click [data-type=edit]': 'edit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
App.Signature.bind 'refresh change', @render
|
||||||
|
App.Signature.fetch()
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
data = App.Signature.all()
|
||||||
|
|
||||||
|
html = $('<div></div>')
|
||||||
|
|
||||||
|
table = @table(
|
||||||
|
model: App.Signature,
|
||||||
|
objects: data,
|
||||||
|
)
|
||||||
|
|
||||||
|
html.append( table )
|
||||||
|
html.append( '<a data-type="new" class="btn">' + T('New') + '</a>' )
|
||||||
|
@html html
|
||||||
|
|
||||||
|
new: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
new App.ChannelEmailSignatureEdit()
|
||||||
|
|
||||||
|
edit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
item = $(e.target).item( App.Signature )
|
||||||
|
@log '123', item, $(e.target)
|
||||||
|
new App.ChannelEmailSignatureEdit( object: item )
|
||||||
|
|
||||||
|
class App.ChannelEmailSignatureEdit extends App.ControllerModal
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render(@object)
|
||||||
|
|
||||||
|
render: (data = {}) ->
|
||||||
|
if @object
|
||||||
|
@html App.view('generic/admin/edit')(
|
||||||
|
head: 'Signature'
|
||||||
|
)
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @el.find('#object_edit'),
|
||||||
|
model: App.Signature,
|
||||||
|
params: @object,
|
||||||
|
autofocus: true,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@html App.view('generic/admin/new')(
|
||||||
|
head: 'Signature'
|
||||||
|
)
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @el.find('#object_new'),
|
||||||
|
model: App.Signature,
|
||||||
|
autofocus: true,
|
||||||
|
)
|
||||||
|
@modalShow()
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
# get params
|
||||||
|
params = @formParam(e.target)
|
||||||
|
|
||||||
|
object = @object || new App.Signature
|
||||||
|
object.load(params)
|
||||||
|
|
||||||
|
# validate form
|
||||||
|
errors = @form.validate( params )
|
||||||
|
|
||||||
|
# show errors in form
|
||||||
|
if errors
|
||||||
|
@log 'error new', errors
|
||||||
|
@formValidate( form: e.target, errors: errors )
|
||||||
|
return false
|
||||||
|
|
||||||
|
# save object
|
||||||
|
object.save(
|
||||||
|
success: =>
|
||||||
|
@modalHide()
|
||||||
|
error: =>
|
||||||
|
@log 'errors'
|
||||||
|
@modalHide()
|
||||||
|
)
|
||||||
|
|
||||||
class App.ChannelEmailInbound extends App.Controller
|
class App.ChannelEmailInbound extends App.Controller
|
||||||
events:
|
events:
|
||||||
'click [data-type=new]': 'new'
|
'click [data-type=new]': 'new'
|
||||||
|
@ -65,13 +244,14 @@ class App.ChannelEmailInbound extends App.Controller
|
||||||
data.push channel
|
data.push channel
|
||||||
|
|
||||||
table = @table(
|
table = @table(
|
||||||
|
header: ['Host', 'User', 'Adapter', 'Active'],
|
||||||
overview: ['host', 'user', 'adapter', 'active'],
|
overview: ['host', 'user', 'adapter', 'active'],
|
||||||
model: App.Channel,
|
model: App.Channel,
|
||||||
objects: data,
|
objects: data,
|
||||||
)
|
)
|
||||||
|
|
||||||
html.append( table )
|
html.append( table )
|
||||||
html.append( '<a data-type="new" class="btn">new account</a>' )
|
html.append( '<a data-type="new" class="btn">' + T('New') + '</a>' )
|
||||||
@html html
|
@html html
|
||||||
|
|
||||||
new: (e) =>
|
new: (e) =>
|
||||||
|
@ -100,14 +280,24 @@ class App.ChannelEmailInboundEdit extends App.ControllerModal
|
||||||
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: @edit_form, nulloption: false, relation: 'Group', class: 'span4', default: data['group_id'] },
|
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: @edit_form, nulloption: false, relation: 'Group', class: 'span4', default: data['group_id'] },
|
||||||
{ name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , class: 'span4', default: data['active'] },
|
{ name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , class: 'span4', default: data['active'] },
|
||||||
]
|
]
|
||||||
@html App.view('generic/admin/new')(
|
if @object
|
||||||
head: 'New Channel'
|
@html App.view('generic/admin/edit')(
|
||||||
)
|
head: 'Channel'
|
||||||
@form = new App.ControllerForm(
|
)
|
||||||
el: @el.find('#object_new'),
|
@form = new App.ControllerForm(
|
||||||
model: { configure_attributes: configure_attributes, className: '' },
|
el: @el.find('#object_edit'),
|
||||||
autofocus: true,
|
model: { configure_attributes: configure_attributes, className: '' },
|
||||||
)
|
autofocus: true,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@html App.view('generic/admin/new')(
|
||||||
|
head: 'Channel'
|
||||||
|
)
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @el.find('#object_new'),
|
||||||
|
model: { configure_attributes: configure_attributes, className: '' },
|
||||||
|
autofocus: true,
|
||||||
|
)
|
||||||
@modalShow()
|
@modalShow()
|
||||||
|
|
||||||
submit: (e) =>
|
submit: (e) =>
|
||||||
|
@ -179,15 +369,17 @@ class App.ChannelEmailOutbound extends App.Controller
|
||||||
adapter_used = channel.adapter
|
adapter_used = channel.adapter
|
||||||
channel_used = channel
|
channel_used = channel
|
||||||
|
|
||||||
if adapter_used is 'Sendmail'
|
configure_attributes = [
|
||||||
configure_attributes = [
|
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , class: 'span4', default: adapter_used },
|
||||||
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , class: 'span4', default: adapter_used },
|
]
|
||||||
]
|
new App.ControllerForm(
|
||||||
@form = new App.ControllerForm(
|
el: @el.find('#form-email-adapter'),
|
||||||
el: @el.find('#form-email-adapter'),
|
model: { configure_attributes: configure_attributes, className: '' },
|
||||||
model: { configure_attributes: configure_attributes, className: '' },
|
autofocus: true,
|
||||||
autofocus: true,
|
)
|
||||||
)
|
|
||||||
|
# if adapter_used is 'Sendmail'
|
||||||
|
# # some form
|
||||||
|
|
||||||
if adapter_used is 'SMTP'
|
if adapter_used is 'SMTP'
|
||||||
configure_attributes = [
|
configure_attributes = [
|
||||||
|
|
|
@ -78,7 +78,7 @@ class _Singleton
|
||||||
|
|
||||||
if _.isArray( params.data )
|
if _.isArray( params.data )
|
||||||
for object in params.data
|
for object in params.data
|
||||||
console.log( 'load ARRAY', object)
|
# console.log( 'load ARRAY', object)
|
||||||
App[params.type].refresh( object, options: { clear: true } )
|
App[params.type].refresh( object, options: { clear: true } )
|
||||||
|
|
||||||
# remember in store if not already requested from local storage
|
# remember in store if not already requested from local storage
|
||||||
|
@ -88,7 +88,7 @@ class _Singleton
|
||||||
|
|
||||||
# if _.isObject( params.data )
|
# if _.isObject( params.data )
|
||||||
for key, object of params.data
|
for key, object of params.data
|
||||||
console.log( 'load OB', object)
|
# console.log( 'load OB', object)
|
||||||
App[params.type].refresh( object, options: { clear: true } )
|
App[params.type].refresh( object, options: { clear: true } )
|
||||||
|
|
||||||
# remember in store if not already requested from local storage
|
# remember in store if not already requested from local storage
|
||||||
|
@ -100,7 +100,7 @@ class _Singleton
|
||||||
console.log( 'find', type, id )
|
console.log( 'find', type, id )
|
||||||
# if App[type].exists( id ) && !callback
|
# if App[type].exists( id ) && !callback
|
||||||
if App[type].exists( id )
|
if App[type].exists( id )
|
||||||
console.log( 'find exists', type, id )
|
# console.log( 'find exists', type, id )
|
||||||
data = App[type].find( id )
|
data = App[type].find( id )
|
||||||
if callback
|
if callback
|
||||||
callback( data )
|
callback( data )
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
class App.Model extends Spine.Model
|
class App.Model extends Spine.Model
|
||||||
|
|
||||||
|
displayName: ->
|
||||||
|
return @name if @name
|
||||||
|
if @realname
|
||||||
|
return "#{@realname} <#{@email}>"
|
||||||
|
if @firstname
|
||||||
|
name = @firstname
|
||||||
|
if @lastname
|
||||||
|
if name
|
||||||
|
name = name + ' '
|
||||||
|
name = name + @lastname
|
||||||
|
return name
|
||||||
|
return '???'
|
||||||
|
|
||||||
@validate: ( data = {} ) ->
|
@validate: ( data = {} ) ->
|
||||||
return if !data['model'].configure_attributes
|
return if !data['model'].configure_attributes
|
||||||
|
|
||||||
|
|
15
app/assets/javascripts/app/models/email_address.js.coffee
Normal file
15
app/assets/javascripts/app/models/email_address.js.coffee
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class App.EmailAddress extends App.Model
|
||||||
|
@configure 'EmailAddress', 'realname', 'email', 'note', 'active'
|
||||||
|
@extend Spine.Model.Ajax
|
||||||
|
@url: '/api/email_addresses'
|
||||||
|
|
||||||
|
@configure_attributes = [
|
||||||
|
{ name: 'realname', display: 'Realname', tag: 'input', type: 'text', limit: 250, 'null': false, 'class': 'span4' },
|
||||||
|
{ name: 'email', display: 'Email', tag: 'input', type: 'text', limit: 250, 'null': false, 'class': 'span4' },
|
||||||
|
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
|
||||||
|
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||||
|
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||||
|
]
|
||||||
|
@configure_overview = [
|
||||||
|
'realname', 'email'
|
||||||
|
]
|
|
@ -1,13 +1,15 @@
|
||||||
class App.Group extends App.Model
|
class App.Group extends App.Model
|
||||||
@configure 'Group', 'name', 'assignment_timeout', 'follow_up_possible', 'follow_up_assignment', 'note', 'active'
|
@configure 'Group', 'name', 'assignment_timeout', 'follow_up_possible', 'follow_up_assignment', 'email_address_id', 'signature_id', 'note', 'active'
|
||||||
@extend Spine.Model.Ajax
|
@extend Spine.Model.Ajax
|
||||||
@url: '/api/groups'
|
@url: '/api/groups'
|
||||||
|
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
||||||
{ name: 'assignment_timeout', display: 'Assignment Timout', tag: 'input', note: 'Assignment timout in minutes if assigned agent is not working on it. Ticket will be shown as unassigend.', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
{ name: 'assignment_timeout', display: 'Assignment Timout', tag: 'input', note: 'Assignment timout in minutes if assigned agent is not working on it. Ticket will be shown as unassigend.', type: 'text', limit: 100, 'null': true, 'class': 'span4' },
|
||||||
{ name: 'follow_up_possible', display: 'Follow possible', tag: 'select', default: 'yes', options: { yes: 'yes', reject: 'reject follow up/do not reopen Ticket', 'new_ticket': 'do not reopen Ticket but create new Ticket' }, 'null': false, note: 'Follow up for closed ticket possible or not.', 'class': 'span4' },
|
{ name: 'follow_up_possible', display: 'Follow possible', tag: 'select', default: 'yes', options: { yes: 'yes', reject: 'reject follow up/do not reopen Ticket', 'new_ticket': 'do not reopen Ticket but create new Ticket' }, 'null': false, note: 'Follow up for closed ticket possible or not.', 'class': 'span4' },
|
||||||
{ name: 'follow_up_assignment', display: 'Assign Follow Ups', tag: 'select', default: 'yes', options: { yes: 'yes', no: 'no' }, 'null': false, note: 'Assign follow up to latest agent again.', 'class': 'span4' },
|
{ name: 'follow_up_assignment', display: 'Assign Follow Ups', tag: 'select', default: 'yes', options: { yes: 'yes', no: 'no' }, 'null': false, note: 'Assign follow up to latest agent again.', 'class': 'span4' },
|
||||||
|
{ name: 'email_address_id', display: 'Email', tag: 'select', multiple: false, null: true, relation: 'EmailAddress', nulloption: true, class: 'span4' },
|
||||||
|
{ name: 'signature_id', display: 'Signature', tag: 'select', multiple: false, null: true, relation: 'Signature', nulloption: true, class: 'span4' },
|
||||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
|
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
|
||||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<form class="form-horizontal" id="mail_adapter">
|
<form class="form-horizontal" id="mail_adapter">
|
||||||
<div id="form-email-adapter"></div>
|
<div id="form-email-adapter"></div>
|
||||||
<div id="form-email-adapter-settings"></div>
|
<div id="form-email-adapter-settings"></div>
|
||||||
<button data-type="" type="submit" class="btn">submit</botton>
|
<button data-type="" type="submit" class="btn"><%- T('Submit') %></botton>
|
||||||
</form>
|
</form>
|
144
app/controllers/email_addresses_controller.rb
Normal file
144
app/controllers/email_addresses_controller.rb
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
class EmailAddressesController < ApplicationController
|
||||||
|
before_filter :authentication_check
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Format:
|
||||||
|
JSON
|
||||||
|
|
||||||
|
Example:
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"realname":"some realname",
|
||||||
|
"email":"system@example.com",
|
||||||
|
"updated_at":"2012-09-14T17:51:53Z",
|
||||||
|
"created_at":"2012-09-14T17:51:53Z",
|
||||||
|
"updated_by_id":2,
|
||||||
|
"created_by_id":2,
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/email_address.json
|
||||||
|
|
||||||
|
Response:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"realname":"some realname1",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"realname":"some realname2",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/email_address.json -v -u #{login}:#{password}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def index
|
||||||
|
model_index_render(EmailAddress, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/email_address/#{id}.json
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "name_1",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/email_address/#{id}.json -v -u #{login}:#{password}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def show
|
||||||
|
model_show_render(EmailAddress, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
POST /api/email_address.json
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
{
|
||||||
|
"realname":"some realname",
|
||||||
|
"email":"system@example.com",
|
||||||
|
"note": "",
|
||||||
|
"active":true,
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"realname":"some realname",
|
||||||
|
"email":"system@example.com",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/email_address.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def create
|
||||||
|
model_create_render(EmailAddress, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
PUT /api/email_address/{id}.json
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
{
|
||||||
|
"realname":"some realname",
|
||||||
|
"email":"system@example.com",
|
||||||
|
"note": "",
|
||||||
|
"active":true,
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"realname":"some realname",
|
||||||
|
"email":"system@example.com",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/email_address.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def update
|
||||||
|
model_update_render(EmailAddress, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
Test:
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
model_destory_render(EmailAddress, params)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,12 +1,19 @@
|
||||||
module ExtraCollection
|
module ExtraCollection
|
||||||
def add(collections)
|
def add(collections)
|
||||||
|
|
||||||
|
# all ticket stuff
|
||||||
collections['TicketStateType'] = Ticket::StateType.all
|
collections['TicketStateType'] = Ticket::StateType.all
|
||||||
collections['TicketState'] = Ticket::State.all
|
collections['TicketState'] = Ticket::State.all
|
||||||
collections['TicketPriority'] = Ticket::Priority.all
|
collections['TicketPriority'] = Ticket::Priority.all
|
||||||
collections['TicketArticleType'] = Ticket::Article::Type.all
|
collections['TicketArticleType'] = Ticket::Article::Type.all
|
||||||
collections['TicketArticleSender'] = Ticket::Article::Sender.all
|
collections['TicketArticleSender'] = Ticket::Article::Sender.all
|
||||||
|
|
||||||
|
# all signatures
|
||||||
|
collections['Signature'] = Signature.all
|
||||||
|
|
||||||
|
# all email addresses
|
||||||
|
collections['EmailAddress'] = EmailAddress.all
|
||||||
|
|
||||||
end
|
end
|
||||||
module_function :add
|
module_function :add
|
||||||
end
|
end
|
141
app/controllers/signatures_controller.rb
Normal file
141
app/controllers/signatures_controller.rb
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
class SignaturesController < ApplicationController
|
||||||
|
before_filter :authentication_check
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Format:
|
||||||
|
JSON
|
||||||
|
|
||||||
|
Example:
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"name":"some signature name",
|
||||||
|
"body":"some signature body",
|
||||||
|
"note":"some note",
|
||||||
|
"updated_at":"2012-09-14T17:51:53Z",
|
||||||
|
"created_at":"2012-09-14T17:51:53Z",
|
||||||
|
"updated_by_id":2,
|
||||||
|
"created_by_id":2,
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/signatures.json
|
||||||
|
|
||||||
|
Response:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "some_name1",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "some_name2",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/signatures.json -v -u #{login}:#{password}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def index
|
||||||
|
model_index_render(Signature, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/signatures/#{id}.json
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "name_1",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/signatures/#{id}.json -v -u #{login}:#{password}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def show
|
||||||
|
model_show_render(Signature, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
POST /api/signatures.json
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
{
|
||||||
|
"name": "some name",
|
||||||
|
"note": "",
|
||||||
|
"active":true,
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "some_name",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/signatures.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def create
|
||||||
|
model_create_render(Signature, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
PUT /api/signatures/{id}.json
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
{
|
||||||
|
"name": "some name",
|
||||||
|
"note": "",
|
||||||
|
"active":true,
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "some_name",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/signatures.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def update
|
||||||
|
model_update_render(Signature, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
Test:
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
model_destory_render(Signature, params)
|
||||||
|
end
|
||||||
|
end
|
6
app/models/email_address.rb
Normal file
6
app/models/email_address.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class EmailAddress < ApplicationModel
|
||||||
|
has_many :groups, :after_add => :cache_update, :after_remove => :cache_update
|
||||||
|
after_create :cache_delete
|
||||||
|
after_update :cache_delete
|
||||||
|
after_destroy :cache_delete
|
||||||
|
end
|
|
@ -1,5 +1,7 @@
|
||||||
class Group < ApplicationModel
|
class Group < ApplicationModel
|
||||||
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
||||||
|
belongs_to :email_address
|
||||||
|
belongs_to :signature
|
||||||
after_create :cache_delete
|
after_create :cache_delete
|
||||||
after_update :cache_delete
|
after_update :cache_delete
|
||||||
after_destroy :cache_delete
|
after_destroy :cache_delete
|
||||||
|
|
6
app/models/signature.rb
Normal file
6
app/models/signature.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class Signature < ApplicationModel
|
||||||
|
has_many :groups, :after_add => :cache_update, :after_remove => :cache_update
|
||||||
|
after_create :cache_delete
|
||||||
|
after_update :cache_delete
|
||||||
|
after_destroy :cache_delete
|
||||||
|
end
|
|
@ -29,27 +29,28 @@ class Ticket::Article < ApplicationModel
|
||||||
|
|
||||||
# set email attributes
|
# set email attributes
|
||||||
if type['name'] == 'email'
|
if type['name'] == 'email'
|
||||||
|
|
||||||
# set subject if empty
|
# set subject if empty
|
||||||
if !self.subject || self.subject == ''
|
if !self.subject || self.subject == ''
|
||||||
self.subject = ticket.title
|
self.subject = ticket.title
|
||||||
end
|
end
|
||||||
|
|
||||||
# clean subject
|
# clean subject
|
||||||
self.subject = ticket.subject_clean(self.subject)
|
self.subject = ticket.subject_clean(self.subject)
|
||||||
|
|
||||||
# generate message id
|
# generate message id
|
||||||
fqdn = Setting.get('fqdn')
|
fqdn = Setting.get('fqdn')
|
||||||
self.message_id = '<' + DateTime.current.to_s(:number) + '.' + self.ticket_id.to_s + '.' + rand(999999).to_s() + '@' + fqdn + '>'
|
self.message_id = '<' + DateTime.current.to_s(:number) + '.' + self.ticket_id.to_s + '.' + rand(999999).to_s() + '@' + fqdn + '>'
|
||||||
|
|
||||||
# set sender
|
# set sender
|
||||||
|
email_address = ticket.group.email_address
|
||||||
|
system_sender = "#{email_address.realname} <#{email_address.email}>"
|
||||||
if Setting.get('ticket_define_email_from') == 'AgentNameSystemAddressName'
|
if Setting.get('ticket_define_email_from') == 'AgentNameSystemAddressName'
|
||||||
seperator = Setting.get('ticket_define_email_from_seperator')
|
seperator = Setting.get('ticket_define_email_from_seperator')
|
||||||
sender = User.find(self.created_by_id)
|
sender = User.find(self.created_by_id)
|
||||||
system_sender = Setting.get('system_sender')
|
|
||||||
self.from = "#{sender.firstname} #{sender.lastname} #{seperator} #{system_sender}"
|
self.from = "#{sender.firstname} #{sender.lastname} #{seperator} #{system_sender}"
|
||||||
else
|
else
|
||||||
self.from = Setting.get('system_sender')
|
self.from = system_sender
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -76,7 +77,8 @@ class Ticket::Article < ApplicationModel
|
||||||
|
|
||||||
# if sender is customer, do not communication
|
# if sender is customer, do not communication
|
||||||
sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first
|
sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first
|
||||||
return 1 if sender == nil || sender['name'] == 'Customer'
|
return 1 if sender == nil
|
||||||
|
return 1 if sender['name'] == 'Customer'
|
||||||
|
|
||||||
type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first
|
type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first
|
||||||
ticket = Ticket.find(self.ticket_id)
|
ticket = Ticket.find(self.ticket_id)
|
||||||
|
|
|
@ -3,68 +3,11 @@ Zammad::Application.routes.draw do
|
||||||
# app init
|
# app init
|
||||||
match '/init', :to => 'init#index'
|
match '/init', :to => 'init#index'
|
||||||
match '/app', :to => 'init#index'
|
match '/app', :to => 'init#index'
|
||||||
|
|
||||||
# You can have the root of your site routed with "root"
|
# You can have the root of your site routed with "root"
|
||||||
# just remember to delete public/index.html.
|
# just remember to delete public/index.html.
|
||||||
root :to => 'init#index'
|
root :to => 'init#index'
|
||||||
|
|
||||||
# The priority is based upon order of creation:
|
|
||||||
# first created -> highest priority.
|
|
||||||
|
|
||||||
# Sample of regular route:
|
|
||||||
# match 'products/:id' => 'catalog#view'
|
|
||||||
# Keep in mind you can assign values other than :controller and :action
|
|
||||||
|
|
||||||
# Sample of named route:
|
|
||||||
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
|
||||||
# This route can be invoked with purchase_url(:id => product.id)
|
|
||||||
|
|
||||||
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
|
||||||
# resources :products
|
|
||||||
|
|
||||||
# Sample resource route with options:
|
|
||||||
# resources :products do
|
|
||||||
# member do
|
|
||||||
# get 'short'
|
|
||||||
# post 'toggle'
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# collection do
|
|
||||||
# get 'sold'
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
# Sample resource route with sub-resources:
|
|
||||||
# resources :products do
|
|
||||||
# resources :comments, :sales
|
|
||||||
# resource :seller
|
|
||||||
# end
|
|
||||||
|
|
||||||
# Sample resource route with more complex sub-resources
|
|
||||||
# resources :products do
|
|
||||||
# resources :comments
|
|
||||||
# resources :sales do
|
|
||||||
# get 'recent', :on => :collection
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
# Sample resource route within a namespace:
|
|
||||||
# namespace :admin do
|
|
||||||
# # Directs /admin/products/* to Admin::ProductsController
|
|
||||||
# # (app/controllers/admin/products_controller.rb)
|
|
||||||
# resources :products
|
|
||||||
# end
|
|
||||||
|
|
||||||
# You can have the root of your site routed with "root"
|
|
||||||
# just remember to delete public/index.html.
|
|
||||||
# root :to => 'welcome#index'
|
|
||||||
|
|
||||||
# See how all your routes lay out with "rake routes"
|
|
||||||
|
|
||||||
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
|
||||||
# Note: This route will make all actions in every controller accessible via GET requests.
|
|
||||||
# match ':controller(/:action(/:id))(.:format)'
|
|
||||||
|
|
||||||
# load routes from external files
|
# load routes from external files
|
||||||
dir = File.expand_path('../', __FILE__)
|
dir = File.expand_path('../', __FILE__)
|
||||||
files = Dir.glob( "#{dir}/routes/*.rb" )
|
files = Dir.glob( "#{dir}/routes/*.rb" )
|
||||||
|
|
12
config/routes/email_address.rb
Normal file
12
config/routes/email_address.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
module ExtraRoutes
|
||||||
|
def add(map)
|
||||||
|
|
||||||
|
# groups
|
||||||
|
map.match '/api/email_addresses', :to => 'email_addresses#index', :via => :get
|
||||||
|
map.match '/api/email_addresses/:id', :to => 'email_addresses#show', :via => :get
|
||||||
|
map.match '/api/email_addresses', :to => 'email_addresses#create', :via => :post
|
||||||
|
map.match '/api/email_addresses/:id', :to => 'email_addresses#update', :via => :put
|
||||||
|
|
||||||
|
end
|
||||||
|
module_function :add
|
||||||
|
end
|
13
config/routes/signature.rb
Normal file
13
config/routes/signature.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module ExtraRoutes
|
||||||
|
def add(map)
|
||||||
|
|
||||||
|
# groups
|
||||||
|
map.match '/api/signatures', :to => 'signatures#index', :via => :get
|
||||||
|
map.match '/api/signatures/:id', :to => 'signatures#show', :via => :get
|
||||||
|
map.match '/api/signatures', :to => 'signatures#create', :via => :post
|
||||||
|
map.match '/api/signatures/:id', :to => 'signatures#update', :via => :put
|
||||||
|
map.match '/api/signatures/:id', :to => 'signatures#destroy', :via => :delete
|
||||||
|
|
||||||
|
end
|
||||||
|
module_function :add
|
||||||
|
end
|
|
@ -54,8 +54,20 @@ class CreateBase < ActiveRecord::Migration
|
||||||
end
|
end
|
||||||
add_index :signatures, [:name], :unique => true
|
add_index :signatures, [:name], :unique => true
|
||||||
|
|
||||||
|
create_table :email_addresses do |t|
|
||||||
|
t.column :realname, :string, :limit => 250, :null => false
|
||||||
|
t.column :email, :string, :limit => 250, :null => false
|
||||||
|
t.column :active, :boolean, :null => false, :default => true
|
||||||
|
t.column :note, :string, :limit => 250, :null => true
|
||||||
|
t.column :updated_by_id, :integer, :null => false
|
||||||
|
t.column :created_by_id, :integer, :null => false
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
add_index :email_addresses, [:email], :unique => true
|
||||||
|
|
||||||
create_table :groups do |t|
|
create_table :groups do |t|
|
||||||
t.references :signature, :null => false
|
t.references :signature, :null => true
|
||||||
|
t.references :email_address, :null => true
|
||||||
t.column :name, :string, :limit => 100, :null => false
|
t.column :name, :string, :limit => 100, :null => false
|
||||||
t.column :assignment_timeout, :integer, :null => true
|
t.column :assignment_timeout, :integer, :null => true
|
||||||
t.column :follow_up_possible, :string, :limit => 100, :default => 'yes', :null => true
|
t.column :follow_up_possible, :string, :limit => 100, :default => 'yes', :null => true
|
||||||
|
|
21
db/migrate/20120930160201_signature_update.rb
Normal file
21
db/migrate/20120930160201_signature_update.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
class SignatureUpdate < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
|
||||||
|
create_table :email_addresses do |t|
|
||||||
|
t.column :realname, :string, :limit => 250, :null => false
|
||||||
|
t.column :email, :string, :limit => 250, :null => false
|
||||||
|
t.column :active, :boolean, :null => false, :default => true
|
||||||
|
t.column :note, :string, :limit => 250, :null => true
|
||||||
|
t.column :updated_by_id, :integer, :null => false
|
||||||
|
t.column :created_by_id, :integer, :null => false
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
add_index :email_addresses, [:email], :unique => true
|
||||||
|
|
||||||
|
add_column :groups, :email_address_id, :integer, :null => true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
38
db/seeds.rb
38
db/seeds.rb
|
@ -986,26 +986,6 @@ Setting.create(
|
||||||
:frontend => false
|
:frontend => false
|
||||||
)
|
)
|
||||||
|
|
||||||
Setting.create(
|
|
||||||
:title => 'System Sender',
|
|
||||||
:name => 'system_sender',
|
|
||||||
:area => 'Email::Base',
|
|
||||||
:description => 'ONLY TEMP!',
|
|
||||||
:options => {
|
|
||||||
:form => [
|
|
||||||
{
|
|
||||||
:display => '',
|
|
||||||
:null => false,
|
|
||||||
:name => 'system_sender',
|
|
||||||
:tag => 'input',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
:state => {
|
|
||||||
:value => 'Zammad Team <zammad@#{config.fqdn}>',
|
|
||||||
},
|
|
||||||
:frontend => false
|
|
||||||
)
|
|
||||||
Setting.create(
|
Setting.create(
|
||||||
:title => 'Block Notifications',
|
:title => 'Block Notifications',
|
||||||
:name => 'send_no_auto_response_reg_exp',
|
:name => 'send_no_auto_response_reg_exp',
|
||||||
|
@ -1052,6 +1032,13 @@ Setting.create(
|
||||||
:frontend => true
|
:frontend => true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
email_address = EmailAddress.create(
|
||||||
|
:id => 1,
|
||||||
|
:realname => 'Zammad',
|
||||||
|
:email => 'zammad@localhost',
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1
|
||||||
|
)
|
||||||
|
|
||||||
Role.create(
|
Role.create(
|
||||||
:id => 1,
|
:id => 1,
|
||||||
|
@ -1076,11 +1063,12 @@ Role.create(
|
||||||
)
|
)
|
||||||
|
|
||||||
Group.create(
|
Group.create(
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:name => 'Users',
|
:name => 'Users',
|
||||||
:note => 'Standard Group/Pool for Tickets.',
|
:email_address_id => email_address.id,
|
||||||
:updated_by_id => 1,
|
:note => 'Standard Group/Pool for Tickets.',
|
||||||
:created_by_id => 1
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1
|
||||||
)
|
)
|
||||||
Group.create(
|
Group.create(
|
||||||
:id => 2,
|
:id => 2,
|
||||||
|
|
Loading…
Reference in a new issue