Merge branch 'develop' of github.com:martini/zammad into develop
This commit is contained in:
commit
50db43318e
16 changed files with 695 additions and 119 deletions
|
@ -226,67 +226,6 @@ class App.ControllerForm extends App.Controller
|
|||
|
||||
if App.UiElement[attribute.tag]
|
||||
item = App.UiElement[attribute.tag].render(attribute, @params, @)
|
||||
###
|
||||
else if key is 'tickets.owner_id' || key is 'tickets.customer_id'
|
||||
display = 'Owner'
|
||||
name = 'owner_id'
|
||||
if key is 'customer_id'
|
||||
display = 'Customer'
|
||||
name = 'customer_id'
|
||||
attribute_config = {
|
||||
name: attribute.name + '::tickets.' + name
|
||||
display: display
|
||||
tag: 'select'
|
||||
multiple: true
|
||||
null: false
|
||||
nulloption: false
|
||||
relation: 'User'
|
||||
value: value || null
|
||||
remove: true
|
||||
filter: ( all, type ) ->
|
||||
return all if type isnt 'collection'
|
||||
all = _.filter( all, (item) ->
|
||||
return if item.id is 1
|
||||
return item
|
||||
)
|
||||
all.unshift( {
|
||||
id: ''
|
||||
name: '--'
|
||||
} )
|
||||
all.unshift( {
|
||||
id: 1
|
||||
name: '*** not set ***'
|
||||
} )
|
||||
all.unshift( {
|
||||
id: 'current_user.id'
|
||||
name: '*** current user ***'
|
||||
} )
|
||||
all
|
||||
}
|
||||
else if key is 'tickets.organization_id'
|
||||
attribute_config = {
|
||||
name: attribute.name + '::tickets.organization_id'
|
||||
display: 'Organization'
|
||||
tag: 'select'
|
||||
multiple: true
|
||||
null: false
|
||||
nulloption: false
|
||||
relation: 'Organization'
|
||||
value: value || null
|
||||
remove: true
|
||||
filter: ( all, type ) ->
|
||||
return all if type isnt 'collection'
|
||||
all.unshift( {
|
||||
id: ''
|
||||
name: '--'
|
||||
} )
|
||||
all.unshift( {
|
||||
id: 'current_user.organization_id'
|
||||
name: '*** organization of current user ***'
|
||||
} )
|
||||
all
|
||||
}
|
||||
###
|
||||
else
|
||||
throw "Invalid UiElement.#{attribute.tag}"
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
# coffeelint: disable=camel_case_classes
|
||||
class App.UiElement.autocompletion_ajax
|
||||
@render: (attribute, params = {}) ->
|
||||
if params[attribute.name]
|
||||
object = App[attribute.relation].find(params[attribute.name])
|
||||
|
||||
if params[attribute.name] || attribute.value
|
||||
object = App[attribute.relation].find(params[attribute.name] || attribute.value)
|
||||
valueName = object.displayName()
|
||||
|
||||
# selectable search
|
||||
searchableAjaxSelectObject = new App.SearchableAjaxSelect(
|
||||
attribute:
|
||||
value: params[attribute.name]
|
||||
value: params[attribute.name] || attribute.value
|
||||
valueName: valueName
|
||||
name: attribute.name
|
||||
id: params.organization_id
|
||||
id: params.organization_id || attribute.value
|
||||
placeholder: App.i18n.translateInline('Search...')
|
||||
limt: 10
|
||||
object: attribute.relation
|
||||
|
|
|
@ -57,7 +57,6 @@ class App.UiElement.ticket_perform_action
|
|||
)
|
||||
|
||||
# build inital params
|
||||
console.log('initial', params[attribute.name])
|
||||
if !_.isEmpty(params[attribute.name])
|
||||
|
||||
selectorExists = false
|
||||
|
|
|
@ -85,7 +85,6 @@ class App.UiElement.ticket_selector
|
|||
)
|
||||
|
||||
# build inital params
|
||||
console.log('initial', params[attribute.name])
|
||||
if !_.isEmpty(params[attribute.name])
|
||||
|
||||
selectorExists = false
|
||||
|
@ -166,7 +165,6 @@ class App.UiElement.ticket_selector
|
|||
)
|
||||
|
||||
@buildValue: (elementFull, elementRow, groupAndAttribute, elements, value, operator, attribute) ->
|
||||
console.log('buildValue', elementFull, elementRow, groupAndAttribute, elements, value, operator, attribute)
|
||||
|
||||
# do nothing if item already exists
|
||||
operator = elementRow.find('.js-operator option:selected').attr('value')
|
||||
|
@ -176,9 +174,16 @@ class App.UiElement.ticket_selector
|
|||
attributeConfig = elements[groupAndAttribute]
|
||||
config = _.clone(attributeConfig)
|
||||
|
||||
# force to use auto compition on user lookup
|
||||
# force to use auto complition on user lookup
|
||||
config.preCondition = false
|
||||
if config.relation is 'User'
|
||||
config.preCondition = 'user'
|
||||
config.tag = 'user_autocompletion'
|
||||
if config.relation is 'Organization'
|
||||
config.tag = 'autocompletion_ajax'
|
||||
config.preCondition = 'org'
|
||||
|
||||
@buildPreCondition(config, elementFull, elementRow, groupAndAttribute, attribute)
|
||||
|
||||
# render ui element
|
||||
item = ''
|
||||
|
@ -204,6 +209,47 @@ class App.UiElement.ticket_selector
|
|||
|
||||
elementRow.find('.js-value').html(item)
|
||||
|
||||
@buildPreCondition: (config, elementFull, elementRow, groupAndAttribute, attribute) ->
|
||||
if !config.preCondition
|
||||
elementRow.find('.js-preCondition').addClass('hide')
|
||||
return
|
||||
|
||||
name = "#{attribute.name}::#{groupAndAttribute}::pre_condition"
|
||||
preConditionCurrent = elementRow.find('.js-preCondition option:selected').attr('value')
|
||||
if !preCondition && attribute.value && attribute.value[groupAndAttribute]
|
||||
preCondition = attribute.value[groupAndAttribute].pre_condition
|
||||
selection = $("<select class=\"form-control\" name=\"#{name}\" ></select>")
|
||||
options = {}
|
||||
if config.preCondition is 'user'
|
||||
options =
|
||||
'set': App.i18n.translateInline('set')
|
||||
'current_user.id': App.i18n.translateInline('current user')
|
||||
'specific': App.i18n.translateInline('specific user')
|
||||
else if config.preCondition is 'org'
|
||||
options =
|
||||
'set': App.i18n.translateInline('set')
|
||||
'current_user.organization_id': App.i18n.translateInline('current user organization')
|
||||
'specific': App.i18n.translateInline('specific organization')
|
||||
for key, value of options
|
||||
selected = preConditionCurrent
|
||||
if key is preCondition
|
||||
selected = 'selected="selected"'
|
||||
selection.append("<option value=\"#{key}\" #{selected}>#{App.i18n.translateInline(value)}</option>")
|
||||
elementRow.find('.js-preCondition').removeClass('hide')
|
||||
elementRow.find('.js-preCondition select').replaceWith(selection)
|
||||
|
||||
toggle = ->
|
||||
preCondition = elementRow.find('.js-preCondition option:selected').attr('value')
|
||||
if preCondition is 'specific'
|
||||
elementRow.find('.js-value').removeClass('hide')
|
||||
else
|
||||
elementRow.find('.js-value').addClass('hide')
|
||||
toggle()
|
||||
|
||||
elementRow.find('.js-preCondition select').bind('change', (e) =>
|
||||
toggle()
|
||||
)
|
||||
|
||||
@buildAttributeSelector: (groups, elements) ->
|
||||
selection = $('<select class="form-control"></select>')
|
||||
for groupKey, groupMeta of groups
|
||||
|
|
|
@ -5,7 +5,7 @@ class App.UserOrganizationAutocompletion extends App.Controller
|
|||
'click .js-organization': 'showOrganizationMembers'
|
||||
'click .js-back': 'hideOrganizationMembers'
|
||||
'click .js-user': 'selectUser'
|
||||
'click .js-user-new': 'newUser'
|
||||
'click .js-userNew': 'newUser'
|
||||
'focus input': 'open'
|
||||
|
||||
constructor: (params) ->
|
||||
|
@ -17,6 +17,10 @@ class App.UserOrganizationAutocompletion extends App.Controller
|
|||
@attribute.source = @apiPath + '/search/user-organization'
|
||||
@build()
|
||||
|
||||
# set current value
|
||||
if @attribute.value
|
||||
@setUser(@attribute.value)
|
||||
|
||||
element: =>
|
||||
@el
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
<%- @Icon('arrow-down', 'dropdown-arrow') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="u-positionOrigin js-preCondition">
|
||||
<select></select>
|
||||
<%- @Icon('arrow-down', 'dropdown-arrow') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls js-value horizontal"></div>
|
||||
</div>
|
||||
<div class="filter-controls">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<li class="recipientList-entry recipientList--new js-user-new" data-user-id="new">
|
||||
<li class="recipientList-entry recipientList--new js-userNew" data-user-id="new">
|
||||
<div class="recipientList-iconSpacer">
|
||||
<%- @Icon('plus', 'recipientList-icon') %>
|
||||
</div>
|
||||
|
|
|
@ -295,7 +295,7 @@ get count of tickets and tickets which match on selector
|
|||
|
||||
def self.selectors(selectors, limit = 10, current_user = nil)
|
||||
fail 'no selectors given' if !selectors
|
||||
query, bind_params, tables = selector2sql(selectors)
|
||||
query, bind_params, tables = selector2sql(selectors, current_user)
|
||||
return [] if !query
|
||||
|
||||
if !current_user
|
||||
|
@ -314,7 +314,7 @@ get count of tickets and tickets which match on selector
|
|||
|
||||
generate condition query to search for tickets based on condition
|
||||
|
||||
query_condition, bind_condition = selector2sql(params[:condition])
|
||||
query_condition, bind_condition = selector2sql(params[:condition], current_user)
|
||||
|
||||
condition example
|
||||
|
||||
|
@ -332,15 +332,31 @@ condition example
|
|||
range: 'day', # minute|hour|day|month|year
|
||||
value: '25',
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is', # is not
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is', # is not
|
||||
pre_condition: 'specific',
|
||||
value: 4711,
|
||||
},
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.selector2sql(selectors)
|
||||
def self.selector2sql(selectors, current_user = nil)
|
||||
current_user_id = UserInfo.current_user_id
|
||||
if current_user
|
||||
current_user_id = current_user.id
|
||||
end
|
||||
return if !selectors
|
||||
|
||||
# remember query and bind params
|
||||
query = ''
|
||||
bind_params = []
|
||||
|
||||
# get tables to join
|
||||
tables = ''
|
||||
selectors.each {|attribute, selector|
|
||||
selector = attribute.split(/\./)
|
||||
|
@ -364,24 +380,71 @@ condition example
|
|||
end
|
||||
}
|
||||
|
||||
# add conditions
|
||||
selectors.each {|attribute, selector_raw|
|
||||
if query != ''
|
||||
query += ' AND '
|
||||
end
|
||||
|
||||
# validation
|
||||
fail "Invalid selector #{selector_raw.inspect}" if !selector_raw
|
||||
fail "Invalid selector #{selector_raw.inspect}" if !selector_raw.respond_to?(:key?)
|
||||
selector = selector_raw.stringify_keys
|
||||
fail "Invalid selector, operator missing #{selector.inspect}" if !selector['operator']
|
||||
return nil if selector['value'].nil?
|
||||
return nil if selector['value'].respond_to?(:empty?) && selector['value'].empty?
|
||||
|
||||
# validate value / allow empty but only if pre_condition eyists
|
||||
if selector['value'].nil? || (selector['value'].respond_to?(:empty?) && selector['value'].empty?)
|
||||
return nil if selector['pre_condition'].nil? || (selector['pre_condition'].respond_to?(:empty?) && selector['pre_condition'].empty?)
|
||||
end
|
||||
|
||||
# validate pre_condition values
|
||||
return nil if selector['pre_condition'] && selector['pre_condition'] !~ /^(set|current_user\.|specific)/
|
||||
|
||||
# get attributes
|
||||
attributes = attribute.split(/\./)
|
||||
attribute = "#{attributes[0]}s.#{attributes[1]}"
|
||||
|
||||
if query != ''
|
||||
query += ' AND '
|
||||
end
|
||||
|
||||
if selector['operator'] == 'is'
|
||||
query += "#{attribute} IN (?)"
|
||||
bind_params.push selector['value']
|
||||
if selector['pre_condition'] == 'set'
|
||||
if attributes[1] =~ /^(created_by|updated_by|owner|customer|user)_id/
|
||||
query += "#{attribute} NOT IN (?)"
|
||||
bind_params.push 1
|
||||
else
|
||||
query += "#{attribute} IS NOT NULL"
|
||||
end
|
||||
elsif selector['pre_condition'] == 'current_user.id'
|
||||
fail "Use current_user.id in selector, but no current_user is set #{selector.inspect}" if !current_user_id
|
||||
query += "#{attribute} IN (?)"
|
||||
bind_params.push current_user_id
|
||||
elsif selector['pre_condition'] == 'current_user.organization_id'
|
||||
fail "Use current_user.id in selector, but no current_user is set #{selector.inspect}" if !current_user_id
|
||||
query += "#{attribute} IN (?)"
|
||||
user = User.lookup(id: current_user_id)
|
||||
bind_params.push user.organization_id
|
||||
else
|
||||
query += "#{attribute} IN (?)"
|
||||
bind_params.push selector['value']
|
||||
end
|
||||
elsif selector['operator'] == 'is not'
|
||||
query += "#{attribute} NOT IN (?)"
|
||||
bind_params.push selector['value']
|
||||
if selector['pre_condition'] == 'set'
|
||||
if attributes[1] =~ /^(created_by|updated_by|owner|customer|user)_id/
|
||||
query += "#{attribute} IN (?)"
|
||||
bind_params.push 1
|
||||
else
|
||||
query += "#{attribute} IS NULL"
|
||||
end
|
||||
elsif selector['pre_condition'] == 'current_user.id'
|
||||
query += "#{attribute} NOT IN (?)"
|
||||
bind_params.push current_user_id
|
||||
elsif selector['pre_condition'] == 'current_user.organization_id'
|
||||
query += "#{attribute} NOT IN (?)"
|
||||
user = User.lookup(id: current_user_id)
|
||||
bind_params.push user.organization_id
|
||||
else
|
||||
query += "#{attribute} NOT IN (?)"
|
||||
bind_params.push selector['value']
|
||||
end
|
||||
elsif selector['operator'] == 'contains'
|
||||
query += "#{attribute} LIKE (?)"
|
||||
value = "%#{selector['value']}%"
|
||||
|
|
|
@ -69,32 +69,6 @@ returns
|
|||
overview_selected = overview
|
||||
overview_selected_raw = Marshal.load( Marshal.dump(overview.attributes) )
|
||||
end
|
||||
|
||||
# replace e.g. 'current_user.id' with current_user.id
|
||||
overview.condition.each { |attribute, content|
|
||||
next if !content
|
||||
next if !content.respond_to?(:key?)
|
||||
next if !content['value']
|
||||
next if content['value'].class != String && content['value'].class != Array
|
||||
|
||||
if content['value'].class == String
|
||||
parts = content['value'].split( '.', 2 )
|
||||
next if !parts[0]
|
||||
next if !parts[1]
|
||||
next if parts[0] != 'current_user'
|
||||
overview.condition[attribute]['value'] = data[:current_user][parts[1].to_sym]
|
||||
next
|
||||
end
|
||||
|
||||
content['value'].each {|item|
|
||||
next if item.class != String
|
||||
parts = item.split('.', 2)
|
||||
next if !parts[0]
|
||||
next if !parts[1]
|
||||
next if parts[0] != 'current_user'
|
||||
item = data[:current_user][parts[1].to_sym]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if data[:view] && !overview_selected
|
||||
|
@ -111,7 +85,7 @@ returns
|
|||
result = []
|
||||
overviews.each { |overview|
|
||||
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview.condition)
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview.condition, data[:current_user])
|
||||
|
||||
# get count
|
||||
count = Ticket.where( access_condition ).where( query_condition, *bind_condition ).count()
|
||||
|
@ -136,7 +110,7 @@ returns
|
|||
order_by = overview_selected.group_by + '_id, ' + order_by
|
||||
end
|
||||
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview_selected.condition)
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview_selected.condition, data[:current_user])
|
||||
|
||||
tickets = Ticket.select('id')
|
||||
.where( access_condition )
|
||||
|
@ -160,7 +134,7 @@ returns
|
|||
|
||||
# get tickets for overview
|
||||
data[:start_page] ||= 1
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview_selected.condition)
|
||||
query_condition, bind_condition = Ticket.selector2sql(overview_selected.condition, data[:current_user])
|
||||
tickets = Ticket.where( access_condition )
|
||||
.where( query_condition, *bind_condition )
|
||||
.order( overview_selected[:order][:by].to_s + ' ' + overview_selected[:order][:direction].to_s )
|
||||
|
|
19
contrib/systemd/zammad.service
Normal file
19
contrib/systemd/zammad.service
Normal file
|
@ -0,0 +1,19 @@
|
|||
[Unit]
|
||||
Description=Zammad
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=<zammad
|
||||
Group=zammad
|
||||
|
||||
ExecStart=bash -l -c "RAILS_ENV=production bundle exec script/websocket-server.rb start -d -i tmp/pids/websocket.pid -p 6042 -b 127.0.0.1"
|
||||
|
||||
ExecStop=bash -l -c "RAILS_ENV=production bundle exec script/websocket-server.rb stop -d -i tmp/pids/websocket.pid -p 6042 -b 127.0.0.1"
|
||||
|
||||
# Give a reasonable amount of time for the server to start up/shut down
|
||||
TimeoutSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
226
db/migrate/20151014000001_update_overview5.rb
Normal file
226
db/migrate/20151014000001_update_overview5.rb
Normal file
|
@ -0,0 +1,226 @@
|
|||
class UpdateOverview5 < ActiveRecord::Migration
|
||||
def up
|
||||
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
UserInfo.current_user_id = 1
|
||||
overview_role = Role.where( name: 'Agent' ).first
|
||||
Overview.create_or_update(
|
||||
name: 'My assigned Tickets',
|
||||
link: 'my_assigned',
|
||||
prio: 1000,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [ 1, 2, 3, 7 ],
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group created_at),
|
||||
s: %w(title customer group created_at),
|
||||
m: %w(number title customer group created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
Overview.create_or_update(
|
||||
name: 'My pending reached Tickets',
|
||||
link: 'my_pending_reached',
|
||||
prio: 1010,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: 3,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
'ticket.pending_time' => {
|
||||
operator: 'within next (relative)',
|
||||
value: 0,
|
||||
range: 'minute',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group created_at),
|
||||
s: %w(title customer group created_at),
|
||||
m: %w(number title customer group created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
Overview.create_or_update(
|
||||
name: 'Unassigned & Open Tickets',
|
||||
link: 'all_unassigned',
|
||||
prio: 1020,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [1, 2, 3],
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group created_at),
|
||||
s: %w(title customer group created_at),
|
||||
m: %w(number title customer group created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
Overview.create_or_update(
|
||||
name: 'All Open Tickets',
|
||||
link: 'all_open',
|
||||
prio: 1030,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [1, 2, 3],
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group state owner created_at),
|
||||
s: %w(title customer group state owner created_at),
|
||||
m: %w(number title customer group state owner created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
Overview.create_or_update(
|
||||
name: 'All pending reached Tickets',
|
||||
link: 'all_pending_reached',
|
||||
prio: 1035,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [3],
|
||||
},
|
||||
'ticket.pending_time' => {
|
||||
operator: 'within next (relative)',
|
||||
value: 0,
|
||||
range: 'minute',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group owner created_at),
|
||||
s: %w(title customer group owner created_at),
|
||||
m: %w(number title customer group owner created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
Overview.create_or_update(
|
||||
name: 'Escalated Tickets',
|
||||
link: 'all_escalated',
|
||||
prio: 1040,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.escalation_time' => {
|
||||
operator: 'within next (relative)',
|
||||
value: '10',
|
||||
range: 'minute',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'escalation_time',
|
||||
direction: 'ASC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer group owner escalation_time),
|
||||
s: %w(title customer group owner escalation_time),
|
||||
m: %w(number title customer group owner escalation_time),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
overview_role = Role.where( name: 'Customer' ).first
|
||||
Overview.create_or_update(
|
||||
name: 'My Tickets',
|
||||
link: 'my_tickets',
|
||||
prio: 1000,
|
||||
role_id: overview_role.id,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [ 1, 2, 3, 4, 6, 7 ],
|
||||
},
|
||||
'ticket.customer_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'DESC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer state created_at),
|
||||
s: %w(number title state created_at),
|
||||
m: %w(number title state created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
Overview.create_or_update(
|
||||
name: 'My Organization Tickets',
|
||||
link: 'my_organization_tickets',
|
||||
prio: 1100,
|
||||
role_id: overview_role.id,
|
||||
organization_shared: true,
|
||||
condition: {
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [ 1, 2, 3, 4, 6, 7 ],
|
||||
},
|
||||
'ticket.organization_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.organization_id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
by: 'created_at',
|
||||
direction: 'DESC',
|
||||
},
|
||||
view: {
|
||||
d: %w(title customer state created_at),
|
||||
s: %w(number title customer state created_at),
|
||||
m: %w(number title customer state created_at),
|
||||
view_mode_default: 's',
|
||||
},
|
||||
)
|
||||
|
||||
end
|
||||
end
|
|
@ -1615,7 +1615,7 @@ Overview.create_if_not_exists(
|
|||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
value: 'current_user.id',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
|
@ -1642,7 +1642,7 @@ Overview.create_if_not_exists(
|
|||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
value: 'current_user.id',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
'ticket.pending_time' => {
|
||||
operator: 'within next (relative)',
|
||||
|
@ -1777,7 +1777,7 @@ Overview.create_if_not_exists(
|
|||
},
|
||||
'ticket.customer_id' => {
|
||||
operator: 'is',
|
||||
value: 'current_user.id',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
|
@ -1804,7 +1804,7 @@ Overview.create_if_not_exists(
|
|||
},
|
||||
'ticket.organization_id' => {
|
||||
operator: 'is',
|
||||
value: 'current_user.organization_id',
|
||||
pre_condition: 'current_user.organization_id',
|
||||
},
|
||||
},
|
||||
order: {
|
||||
|
|
22
extras/zammad_nginx.conf
Normal file
22
extras/zammad_nginx.conf
Normal file
|
@ -0,0 +1,22 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name SERVER_NAME;
|
||||
root /opt/zammad/zammad/public;
|
||||
|
||||
location ~ ^/(assets/|robots.txt|humans.txt|favicon.ico) {
|
||||
expires max;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_pass http://localhost:6042;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://localhost:3000;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// form
|
||||
test( 'form checks', function() {
|
||||
|
||||
App.TicketPriority.refresh( [
|
||||
App.TicketPriority.refresh([
|
||||
{
|
||||
id: 1,
|
||||
name: '1 low',
|
||||
|
@ -31,7 +31,28 @@ test( 'form checks', function() {
|
|||
active: true,
|
||||
created_at: '2014-06-10T10:17:54.000Z',
|
||||
},
|
||||
] )
|
||||
])
|
||||
|
||||
App.User.refresh([
|
||||
{
|
||||
id: 47,
|
||||
login: 'bod@example.com',
|
||||
email: 'bod@example.com',
|
||||
firstname: 'Bob',
|
||||
lastname: 'Smith',
|
||||
active: true,
|
||||
created_at: '2014-06-10T11:17:34.000Z',
|
||||
},
|
||||
])
|
||||
|
||||
App.Organization.refresh([
|
||||
{
|
||||
id: 12,
|
||||
name: 'Org 1',
|
||||
active: true,
|
||||
created_at: '2014-06-10T11:19:34.000Z',
|
||||
},
|
||||
])
|
||||
|
||||
$('#forms').append('<hr><h1>form time check</h1><form id="form1"></form>')
|
||||
|
||||
|
@ -98,6 +119,16 @@ test( 'form checks', function() {
|
|||
operator: 'before (absolute)',
|
||||
value: '2015-09-20T03:41:00.000Z',
|
||||
},
|
||||
'ticket.organization_id': {
|
||||
operator: 'is not',
|
||||
pre_condition: 'specific',
|
||||
value: 12,
|
||||
},
|
||||
'ticket.owner_id': {
|
||||
operator: 'is',
|
||||
pre_condition: 'specific',
|
||||
value: 47,
|
||||
},
|
||||
},
|
||||
executions: {
|
||||
'ticket.title': {
|
||||
|
@ -143,6 +174,17 @@ test( 'form checks', function() {
|
|||
operator: 'before (absolute)',
|
||||
value: '2015-09-20T03:41:00.000Z',
|
||||
},
|
||||
'ticket.organization_id': {
|
||||
operator: 'is not',
|
||||
pre_condition: 'specific',
|
||||
value: '12',
|
||||
},
|
||||
'ticket.owner_id': {
|
||||
operator: 'is',
|
||||
pre_condition: 'specific',
|
||||
value: '47',
|
||||
value_completion: 'Bob Smith <bod@example.com>',
|
||||
},
|
||||
},
|
||||
executions: {
|
||||
'ticket.title': {
|
||||
|
@ -270,6 +312,17 @@ test( 'form checks', function() {
|
|||
operator: 'before (absolute)',
|
||||
value: '2015-09-20T03:41:00.000Z',
|
||||
},
|
||||
'ticket.organization_id': {
|
||||
operator: 'is not',
|
||||
pre_condition: 'specific',
|
||||
value: '12',
|
||||
},
|
||||
'ticket.owner_id': {
|
||||
operator: 'is',
|
||||
pre_condition: 'specific',
|
||||
value: '47',
|
||||
value_completion: 'Bob Smith <bod@example.com>',
|
||||
},
|
||||
},
|
||||
executions: {
|
||||
'ticket.priority_id': {
|
||||
|
|
|
@ -29,7 +29,7 @@ class AgentUserManageTest < TestCase
|
|||
sleep 1
|
||||
sendkey( value: :arrow_down )
|
||||
sleep 0.5
|
||||
click( css: '.active .newTicket .recipientList-entry.js-user-new' )
|
||||
click( css: '.active .newTicket .recipientList-entry.js-userNew' )
|
||||
sleep 1
|
||||
|
||||
set(
|
||||
|
|
|
@ -621,6 +621,230 @@ class TicketSelectorTest < ActiveSupport::TestCase
|
|||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
# with owner/customer/org
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'specific',
|
||||
value: agent1.id,
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'set',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is not',
|
||||
pre_condition: 'set',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
UserInfo.current_user_id = agent1.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
UserInfo.current_user_id = agent2.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.owner_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
UserInfo.current_user_id = customer1.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.customer_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
UserInfo.current_user_id = customer2.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.customer_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
UserInfo.current_user_id = customer1.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.organization_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.organization_id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
UserInfo.current_user_id = customer2.id
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.organization_id' => {
|
||||
operator: 'is',
|
||||
pre_condition: 'current_user.organization_id',
|
||||
},
|
||||
}
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal( ticket_count, 1 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal( ticket_count, 0 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue