Init sla management feature.
This commit is contained in:
parent
6aac51b633
commit
c21f1ce93f
17 changed files with 516 additions and 435 deletions
|
@ -227,284 +227,6 @@ class App.ControllerForm extends App.Controller
|
||||||
if App.UiElement[attribute.tag]
|
if App.UiElement[attribute.tag]
|
||||||
item = App.UiElement[attribute.tag].render(attribute, @params, @)
|
item = App.UiElement[attribute.tag].render(attribute, @params, @)
|
||||||
|
|
||||||
# working_hour
|
|
||||||
else if attribute.tag is 'time_before_last'
|
|
||||||
if !attribute.value
|
|
||||||
attribute.value = {}
|
|
||||||
item = $( App.view('generic/time_before_last')( attribute: attribute ) )
|
|
||||||
item.find( "[name=\"#{attribute.name}::direction\"]").find("option[value=\"#{attribute.value.direction}\"]").attr( 'selected', 'selected' )
|
|
||||||
item.find( "[name=\"#{attribute.name}::count\"]").find("option[value=\"#{attribute.value.count}\"]").attr( 'selected', 'selected' )
|
|
||||||
item.find( "[name=\"#{attribute.name}::area\"]").find("option[value=\"#{attribute.value.area}\"]").attr( 'selected', 'selected' )
|
|
||||||
|
|
||||||
# ticket attribute set
|
|
||||||
else if attribute.tag is 'ticket_attribute_set'
|
|
||||||
|
|
||||||
# list of possible attributes
|
|
||||||
item = $(
|
|
||||||
App.view('generic/ticket_attribute_manage')(
|
|
||||||
attribute: attribute
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
addShownAttribute = ( key, value ) =>
|
|
||||||
parts = key.split(/::/)
|
|
||||||
key = parts[0]
|
|
||||||
type = parts[1]
|
|
||||||
if key is 'tickets.title'
|
|
||||||
attribute_config = {
|
|
||||||
name: attribute.name + '::tickets.title'
|
|
||||||
display: 'Title'
|
|
||||||
tag: 'input'
|
|
||||||
type: 'text'
|
|
||||||
null: false
|
|
||||||
value: value
|
|
||||||
remove: true
|
|
||||||
}
|
|
||||||
else if key is 'tickets.group_id'
|
|
||||||
attribute_config = {
|
|
||||||
name: attribute.name + '::tickets.group_id'
|
|
||||||
display: 'Group'
|
|
||||||
tag: 'select'
|
|
||||||
multiple: false
|
|
||||||
null: false
|
|
||||||
nulloption: false
|
|
||||||
relation: 'Group'
|
|
||||||
value: value
|
|
||||||
remove: true
|
|
||||||
}
|
|
||||||
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: false
|
|
||||||
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: false
|
|
||||||
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 if key is 'tickets.state_id'
|
|
||||||
attribute_config = {
|
|
||||||
name: attribute.name + '::tickets.state_id'
|
|
||||||
display: 'State'
|
|
||||||
tag: 'select'
|
|
||||||
multiple: false
|
|
||||||
null: false
|
|
||||||
nulloption: false
|
|
||||||
relation: 'TicketState'
|
|
||||||
value: value
|
|
||||||
translate: true
|
|
||||||
remove: true
|
|
||||||
}
|
|
||||||
else if key is 'tickets.priority_id'
|
|
||||||
attribute_config = {
|
|
||||||
name: attribute.name + '::tickets.priority_id'
|
|
||||||
display: 'Priority'
|
|
||||||
tag: 'select'
|
|
||||||
multiple: false
|
|
||||||
null: false
|
|
||||||
nulloption: false
|
|
||||||
relation: 'TicketPriority'
|
|
||||||
value: value
|
|
||||||
translate: true
|
|
||||||
remove: true
|
|
||||||
}
|
|
||||||
else
|
|
||||||
attribute_config = {
|
|
||||||
name: attribute.name + '::' + key
|
|
||||||
display: 'FIXME!'
|
|
||||||
tag: 'input'
|
|
||||||
type: 'text'
|
|
||||||
value: value
|
|
||||||
remove: true
|
|
||||||
}
|
|
||||||
item.find('select[name=ticket_attribute_list] option[value="' + key + '"]').hide().prop('disabled', true)
|
|
||||||
|
|
||||||
itemSub = @formGenItem( attribute_config )
|
|
||||||
itemSub.find('.glyphicon-minus').bind('click', (e) ->
|
|
||||||
e.preventDefault()
|
|
||||||
value = $(e.target).closest('.controls').find('[name]').attr('name')
|
|
||||||
if value
|
|
||||||
value = value.replace("#{attribute.name}::", '')
|
|
||||||
$(e.target).closest('.sub_attribute').find('select[name=ticket_attribute_list] option[value="' + value + '"]').show().prop('disabled', false)
|
|
||||||
$(@).parent().parent().parent().remove()
|
|
||||||
)
|
|
||||||
# itemSub.append('<a href=\"#\" class=\"icon-minus\"></a>')
|
|
||||||
item.find('.ticket_attribute_item').append( itemSub )
|
|
||||||
|
|
||||||
# list of existing attributes
|
|
||||||
attribute_config = {
|
|
||||||
name: 'ticket_attribute_list'
|
|
||||||
display: 'Add Attribute'
|
|
||||||
tag: 'select'
|
|
||||||
multiple: false
|
|
||||||
null: false
|
|
||||||
# nulloption: true
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: ''
|
|
||||||
name: '-- Ticket --'
|
|
||||||
selected: false
|
|
||||||
disable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tickets.title'
|
|
||||||
name: 'Title'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tickets.group_id'
|
|
||||||
name: 'Group'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tickets.state_id'
|
|
||||||
name: 'State'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tickets.priority_id'
|
|
||||||
name: 'Priority'
|
|
||||||
selected: true
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tickets.owner_id'
|
|
||||||
name: 'Owner'
|
|
||||||
selected: true
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
# # {
|
|
||||||
# value: 'tag'
|
|
||||||
# name: 'Tag'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: '-a'
|
|
||||||
# name: '-- ' + App.i18n.translateInline('Article') + ' --'
|
|
||||||
# selected: false
|
|
||||||
# disable: true
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: 'ticket_articles.from'
|
|
||||||
# name: 'From'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: 'ticket_articles.to'
|
|
||||||
# name: 'To'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: 'ticket_articles.cc'
|
|
||||||
# name: 'Cc'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: 'ticket_articles.subject'
|
|
||||||
# name: 'Subject'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# value: 'ticket_articles.body'
|
|
||||||
# name: 'Text'
|
|
||||||
# selected: true
|
|
||||||
# disable: false
|
|
||||||
# },
|
|
||||||
{
|
|
||||||
value: '-c'
|
|
||||||
name: '-- ' + App.i18n.translateInline('Customer') + ' --'
|
|
||||||
selected: false
|
|
||||||
disable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'customers.id'
|
|
||||||
name: 'Customer'
|
|
||||||
selected: true
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'organization.id'
|
|
||||||
name: 'Organization'
|
|
||||||
selected: true
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
]
|
|
||||||
default: ''
|
|
||||||
translate: true
|
|
||||||
class: 'medium'
|
|
||||||
add: true
|
|
||||||
}
|
|
||||||
list = @formGenItem( attribute_config )
|
|
||||||
list.find('.glyphicon-plus').bind('click', (e) ->
|
|
||||||
e.preventDefault()
|
|
||||||
value = $(e.target).closest('.controls').find('[name=ticket_attribute_list]').val()
|
|
||||||
addShownAttribute( value, '' )
|
|
||||||
)
|
|
||||||
item.find('.ticket_attribute_list').prepend( list )
|
|
||||||
|
|
||||||
# list of shown attributes
|
|
||||||
show = []
|
|
||||||
if attribute.value
|
|
||||||
for key, value of attribute.value
|
|
||||||
addShownAttribute( key, value )
|
|
||||||
|
|
||||||
# ticket attribute selection
|
# ticket attribute selection
|
||||||
else if attribute.tag is 'ticket_attribute_selection'
|
else if attribute.tag is 'ticket_attribute_selection'
|
||||||
|
|
||||||
|
@ -948,92 +670,8 @@ class App.ControllerForm extends App.Controller
|
||||||
for key, value of attribute.value
|
for key, value of attribute.value
|
||||||
addShownAttribute( key, value )
|
addShownAttribute( key, value )
|
||||||
|
|
||||||
# timeplan
|
|
||||||
else if attribute.tag is 'timeplan'
|
|
||||||
item = $( App.view('generic/timeplan')( attribute: attribute ) )
|
|
||||||
attribute_config = {
|
|
||||||
name: "#{attribute.name}::days"
|
|
||||||
tag: 'select'
|
|
||||||
multiple: true
|
|
||||||
null: false
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'mon'
|
|
||||||
name: 'Monday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'tue'
|
|
||||||
name: 'Tuesday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'wed'
|
|
||||||
name: 'Wednesday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'thu'
|
|
||||||
name: 'Thursday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'fri'
|
|
||||||
name: 'Friday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'sat'
|
|
||||||
name: 'Saturday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'sun'
|
|
||||||
name: 'Sunday'
|
|
||||||
selected: false
|
|
||||||
disable: false
|
|
||||||
},
|
|
||||||
]
|
|
||||||
default: attribute.default?.days
|
|
||||||
}
|
|
||||||
item.find('.days').append( @formGenItem( attribute_config ) )
|
|
||||||
|
|
||||||
hours = {}
|
|
||||||
for hour in [0..23]
|
|
||||||
localHour = "0#{hour}"
|
|
||||||
hours[hour] = localHour.substr(localHour.length-2,2)
|
|
||||||
attribute_config = {
|
|
||||||
name: "#{attribute.name}::hours"
|
|
||||||
tag: 'select'
|
|
||||||
multiple: true
|
|
||||||
null: false
|
|
||||||
options: hours
|
|
||||||
default: attribute.default?.hours
|
|
||||||
}
|
|
||||||
item.find('.hours').append( @formGenItem( attribute_config ) )
|
|
||||||
|
|
||||||
minutes = {}
|
|
||||||
for minute in [0..5]
|
|
||||||
minutes["#{minute}0"] = "#{minute}0"
|
|
||||||
attribute_config = {
|
|
||||||
name: "#{attribute.name}::minutes"
|
|
||||||
tag: 'select'
|
|
||||||
multiple: true
|
|
||||||
null: false
|
|
||||||
options: minutes
|
|
||||||
default: attribute.default?.miuntes
|
|
||||||
}
|
|
||||||
item.find('.minutes').append( @formGenItem( attribute_config ) )
|
|
||||||
|
|
||||||
# input
|
|
||||||
else
|
else
|
||||||
item = $( App.view('generic/input')( attribute: attribute ) )
|
throw "Invalid UiElement.#{attribute.tag}"
|
||||||
|
|
||||||
if @handlers
|
if @handlers
|
||||||
item.bind('change', (e) =>
|
item.bind('change', (e) =>
|
||||||
|
@ -1193,7 +831,7 @@ class App.ControllerForm extends App.Controller
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# collect all params, push it to an array if already exists
|
# collect all params, push it to an array if already exists
|
||||||
if param[key.name]
|
if param[key.name] isnt undefined
|
||||||
if typeof param[key.name] is 'string'
|
if typeof param[key.name] is 'string'
|
||||||
param[key.name] = [param[key.name], key.value]
|
param[key.name] = [param[key.name], key.value]
|
||||||
else
|
else
|
||||||
|
@ -1293,15 +931,13 @@ class App.ControllerForm extends App.Controller
|
||||||
inputSelectObject = {}
|
inputSelectObject = {}
|
||||||
for key of param
|
for key of param
|
||||||
parts = key.split '::'
|
parts = key.split '::'
|
||||||
if parts[0] && parts[1] && !parts[2]
|
if parts[0] && parts[1]
|
||||||
if !inputSelectObject[ parts[0] ]
|
if !(parts[0] of inputSelectObject)
|
||||||
inputSelectObject[ parts[0] ] = {}
|
inputSelectObject[ parts[0] ] = {}
|
||||||
|
if !parts[2]
|
||||||
inputSelectObject[ parts[0] ][ parts[1] ] = param[ key ]
|
inputSelectObject[ parts[0] ][ parts[1] ] = param[ key ]
|
||||||
delete param[ key ]
|
else
|
||||||
if parts[0] && parts[1] && parts[2]
|
if !(parts[1] of inputSelectObject[ parts[0] ])
|
||||||
if !inputSelectObject[ parts[0] ]
|
|
||||||
inputSelectObject[ parts[0] ] = {}
|
|
||||||
if !inputSelectObject[ parts[0] ][ parts[1] ]
|
|
||||||
inputSelectObject[ parts[0] ][ parts[1] ] = {}
|
inputSelectObject[ parts[0] ][ parts[1] ] = {}
|
||||||
inputSelectObject[ parts[0] ][ parts[1] ][ parts[2] ] = param[ key ]
|
inputSelectObject[ parts[0] ][ parts[1] ][ parts[2] ] = param[ key ]
|
||||||
delete param[ key ]
|
delete param[ key ]
|
||||||
|
@ -1311,7 +947,7 @@ class App.ControllerForm extends App.Controller
|
||||||
param[ key ] = inputSelectObject[ key ]
|
param[ key ] = inputSelectObject[ key ]
|
||||||
|
|
||||||
#App.Log.notice 'ControllerForm', 'formParam', form, param
|
#App.Log.notice 'ControllerForm', 'formParam', form, param
|
||||||
return param
|
param
|
||||||
|
|
||||||
@formId: ->
|
@formId: ->
|
||||||
formId = new Date().getTime() + Math.floor( Math.random() * 99999 )
|
formId = new Date().getTime() + Math.floor( Math.random() * 99999 )
|
||||||
|
|
|
@ -196,6 +196,7 @@ class App.ControllerGenericIndex extends App.Controller
|
||||||
pageData: @pageData
|
pageData: @pageData
|
||||||
genericObject: @genericObject
|
genericObject: @genericObject
|
||||||
container: @container
|
container: @container
|
||||||
|
large: @large
|
||||||
)
|
)
|
||||||
|
|
||||||
new: (e) ->
|
new: (e) ->
|
||||||
|
@ -204,6 +205,7 @@ class App.ControllerGenericIndex extends App.Controller
|
||||||
pageData: @pageData
|
pageData: @pageData
|
||||||
genericObject: @genericObject
|
genericObject: @genericObject
|
||||||
container: @container
|
container: @container
|
||||||
|
large: @large
|
||||||
)
|
)
|
||||||
|
|
||||||
description: (e) =>
|
description: (e) =>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
class App.UiElement.autocompletion_ajax
|
||||||
|
@render: (attribute, params = {}) ->
|
||||||
|
if params[attribute.name]
|
||||||
|
object = App[attribute.relation].find(params[attribute.name])
|
||||||
|
valueName = object.displayName()
|
||||||
|
|
||||||
|
# selectable search
|
||||||
|
searchableAjaxSelectObject = new App.SearchableAjaxSelect(
|
||||||
|
attribute:
|
||||||
|
value: params[attribute.name]
|
||||||
|
valueName: valueName
|
||||||
|
name: attribute.name
|
||||||
|
id: params.organization_id
|
||||||
|
placeholder: App.i18n.translateInline('Search...')
|
||||||
|
limt: 10
|
||||||
|
object: attribute.relation
|
||||||
|
)
|
||||||
|
searchableAjaxSelectObject.element()
|
|
@ -0,0 +1,3 @@
|
||||||
|
class App.UiElement.input
|
||||||
|
@render: (attribute) ->
|
||||||
|
$( App.view('generic/input')( attribute: attribute ) )
|
|
@ -1,5 +1,5 @@
|
||||||
class App.UiElement.select extends App.UiElement.ApplicationUiElement
|
class App.UiElement.select extends App.UiElement.ApplicationUiElement
|
||||||
@render: (attribute, params, form_controller) ->
|
@render: (attribute, params) ->
|
||||||
|
|
||||||
# set multiple option
|
# set multiple option
|
||||||
if attribute.multiple
|
if attribute.multiple
|
||||||
|
|
|
@ -1,4 +1,46 @@
|
||||||
class App.UiElement.sla_times
|
class App.UiElement.sla_times
|
||||||
@render: (attribute) ->
|
@render: (attribute, params = {}) ->
|
||||||
|
|
||||||
$( App.view('generic/sla_times')( attribute: attribute ) )
|
item = $( App.view('generic/sla_times')(
|
||||||
|
attribute: attribute
|
||||||
|
first_response_time: params.first_response_time
|
||||||
|
update_time: params.update_time
|
||||||
|
close_time: params.close_time
|
||||||
|
first_response_time_in_text: @toText(params.first_response_time)
|
||||||
|
update_time_in_text: @toText(params.update_time)
|
||||||
|
close_time_in_text: @toText(params.close_time)
|
||||||
|
) )
|
||||||
|
|
||||||
|
item.find('.js-timeConvertFrom').bind('keyup', (e) =>
|
||||||
|
inText = $(e.target).val()
|
||||||
|
inMinutes = @toMinutes(inText)
|
||||||
|
if !inMinutes
|
||||||
|
$(e.target).addClass('has-error')
|
||||||
|
else
|
||||||
|
$(e.target).removeClass('has-error')
|
||||||
|
dest = $(e.target).closest('td').find('.js-timeConvertTo')
|
||||||
|
dest.val(inMinutes)
|
||||||
|
)
|
||||||
|
|
||||||
|
item
|
||||||
|
|
||||||
|
@toMinutes: (hh) ->
|
||||||
|
hh = hh.split(':')
|
||||||
|
hour = parseInt(hh[0])
|
||||||
|
minute = parseInt(hh[1])
|
||||||
|
return if hour is NaN
|
||||||
|
return if minute is NaN
|
||||||
|
(hour * 60) + minute
|
||||||
|
|
||||||
|
@toText: (m) ->
|
||||||
|
m = parseInt(m)
|
||||||
|
return if !m
|
||||||
|
minutes = m % 60
|
||||||
|
hours = Math.floor(m / 60)
|
||||||
|
|
||||||
|
if minutes < 10
|
||||||
|
minutes = "0#{minutes}"
|
||||||
|
if hours < 10
|
||||||
|
hours = "0#{hours}"
|
||||||
|
|
||||||
|
"#{hours}:#{minutes}"
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
class App.UiElement.ticket_selector extends App.UiElement.ApplicationUiElement
|
||||||
|
@render: (attribute, params = {}) ->
|
||||||
|
|
||||||
|
# list of attributes
|
||||||
|
groups =
|
||||||
|
tickets:
|
||||||
|
name: 'Ticket'
|
||||||
|
model: 'Ticket'
|
||||||
|
users:
|
||||||
|
name: 'Customer'
|
||||||
|
model: 'User'
|
||||||
|
organizations:
|
||||||
|
name: 'Organization'
|
||||||
|
model: 'Organization'
|
||||||
|
|
||||||
|
elements =
|
||||||
|
tickets:
|
||||||
|
title:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
number:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
group_id:
|
||||||
|
relation: 'Group'
|
||||||
|
tag: 'select'
|
||||||
|
multible: true
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
priority_id:
|
||||||
|
relation: 'Priority'
|
||||||
|
tag: 'select'
|
||||||
|
multible: true
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
state_id:
|
||||||
|
relation: 'State'
|
||||||
|
tag: 'select'
|
||||||
|
multible: true
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
owner_id:
|
||||||
|
tag: 'user_selection'
|
||||||
|
relation: 'User'
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
customer_id:
|
||||||
|
tag: 'user_selection'
|
||||||
|
relation: 'User'
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
organization_id:
|
||||||
|
tag: ''
|
||||||
|
relation: 'Organization'
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
tag:
|
||||||
|
tag: 'tag'
|
||||||
|
multible: true
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
created_at:
|
||||||
|
tag: 'timestamp'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
updated_at:
|
||||||
|
tag: 'timestamp'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
escalation_time:
|
||||||
|
tag: 'timestamp'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
users:
|
||||||
|
firstname:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
lastname:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
email:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
login:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
created_at:
|
||||||
|
tag: 'time_selector_enhanced'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
updated_at:
|
||||||
|
tag: 'time_selector_enhanced'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
organizations:
|
||||||
|
name:
|
||||||
|
tag: 'input'
|
||||||
|
operator: ['contains', 'contains not']
|
||||||
|
shared:
|
||||||
|
tag: 'boolean'
|
||||||
|
operator: ['is', 'is not']
|
||||||
|
created_at:
|
||||||
|
tag: 'time_selector_enhanced'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
updated_at:
|
||||||
|
tag: 'time_selector_enhanced'
|
||||||
|
operator: ['before', 'after']
|
||||||
|
|
||||||
|
# megre config
|
||||||
|
for groupKey, groupMeta of groups
|
||||||
|
for elementKey, elementGroup of elements
|
||||||
|
if elementKey is groupKey
|
||||||
|
configure_attributes = App[groupMeta.model].configure_attributes
|
||||||
|
for attributeName, attributeConfig of elementGroup
|
||||||
|
for attribute in configure_attributes
|
||||||
|
if attribute.name is attributeName
|
||||||
|
attributeConfig.config = attribute
|
||||||
|
|
||||||
|
selector = @buildAttributeSelector(groups, elements)
|
||||||
|
|
||||||
|
# return item
|
||||||
|
item = $( App.view('generic/ticket_selector')( attribute: attribute ) )
|
||||||
|
item.find('.js-attributeSelector').prepend(selector)
|
||||||
|
|
||||||
|
# add filter
|
||||||
|
item.find('.js-add').bind('click', (e) =>
|
||||||
|
element = $(e.target).closest('.js-filterElement')
|
||||||
|
elementClone = element.clone(true)
|
||||||
|
element.after(elementClone)
|
||||||
|
elementClone.find('.js-attributeSelector select').trigger('change')
|
||||||
|
)
|
||||||
|
|
||||||
|
# remove filter
|
||||||
|
item.find('.js-remove').bind('click', (e) =>
|
||||||
|
$(e.target).closest('.js-filterElement').remove()
|
||||||
|
@rebuildAttributeSelectors(item)
|
||||||
|
)
|
||||||
|
|
||||||
|
# change filter
|
||||||
|
item.find('.js-attributeSelector select').bind('change', (e) =>
|
||||||
|
groupAndAttribute = $(e.target).find('option:selected').attr('value')
|
||||||
|
elementRow = $(e.target).closest('.js-filterElement')
|
||||||
|
|
||||||
|
console.log('CHANGE', groupAndAttribute, $(e.target))
|
||||||
|
|
||||||
|
@rebuildAttributeSelectors(item, elementRow, groupAndAttribute)
|
||||||
|
@rebuildOperater(item, elementRow, groupAndAttribute, elements)
|
||||||
|
@buildValue(item, elementRow, groupAndAttribute, elements)
|
||||||
|
)
|
||||||
|
|
||||||
|
# build inital params
|
||||||
|
console.log('P', params)
|
||||||
|
if !_.isEmpty(params.condition)
|
||||||
|
selectorExists = false
|
||||||
|
for position of params.condition.attribute
|
||||||
|
|
||||||
|
# get stored params
|
||||||
|
groupAndAttribute = params.condition.attribute[position]
|
||||||
|
if params.condition[groupAndAttribute]
|
||||||
|
selectorExists = true
|
||||||
|
operator = params.condition[groupAndAttribute].operator
|
||||||
|
value = params.condition[groupAndAttribute].value
|
||||||
|
|
||||||
|
# get selector rows
|
||||||
|
elementFirst = item.find('.js-filterElement').first()
|
||||||
|
elementLast = item.find('.js-filterElement').last()
|
||||||
|
|
||||||
|
# clone, rebuild and append
|
||||||
|
elementClone = elementFirst.clone(true)
|
||||||
|
@rebuildAttributeSelectors(item, elementClone, groupAndAttribute)
|
||||||
|
@rebuildOperater(item, elementClone, groupAndAttribute, elements, operator)
|
||||||
|
@buildValue(item, elementClone, groupAndAttribute, elements, value)
|
||||||
|
elementLast.after(elementClone)
|
||||||
|
|
||||||
|
# remove first dummy row
|
||||||
|
if selectorExists
|
||||||
|
item.find('.js-filterElement').first().remove()
|
||||||
|
item
|
||||||
|
|
||||||
|
@getElementConfig: (groupAndAttribute, elements) ->
|
||||||
|
for elementGroup, elementConfig of elements
|
||||||
|
for elementKey, elementItem of elementConfig
|
||||||
|
if "#{elementGroup}.#{elementKey}" is groupAndAttribute
|
||||||
|
return elementItem
|
||||||
|
false
|
||||||
|
|
||||||
|
@buildValue: (elementFull, elementRow, groupAndAttribute, elements, value) ->
|
||||||
|
|
||||||
|
# do nothing if item already exists
|
||||||
|
name = "condition::#{groupAndAttribute}::value"
|
||||||
|
return if elementRow.find("[name=\"#{name}\"]").get(0)
|
||||||
|
|
||||||
|
# build new item
|
||||||
|
attributeConfig = @getElementConfig(groupAndAttribute, elements)
|
||||||
|
item = ''
|
||||||
|
if attributeConfig && attributeConfig.config && App.UiElement[attributeConfig.config.tag]
|
||||||
|
config = _.clone(attributeConfig.config)
|
||||||
|
config['name'] = name
|
||||||
|
config['value'] = value
|
||||||
|
if 'multiple' of config
|
||||||
|
config.multiple = true
|
||||||
|
config.nulloption = false
|
||||||
|
item = App.UiElement[attributeConfig.config.tag].render(config, {})
|
||||||
|
elementRow.find('.js-value').html(item)
|
||||||
|
|
||||||
|
@buildAttributeSelector: (groups, elements) ->
|
||||||
|
selection = $('<input type="hidden" name="condition::attribute"><select class="form-control"></select>')
|
||||||
|
for groupKey, groupMeta of groups
|
||||||
|
displayName = App.i18n.translateInline(groupMeta.name)
|
||||||
|
selection.closest('select').append("<optgroup label=\"#{displayName}\" class=\"js-#{groupKey}\"></optgroup>")
|
||||||
|
optgroup = selection.find("optgroup.js-#{groupKey}")
|
||||||
|
for elementKey, elementGroup of elements
|
||||||
|
if elementKey is groupKey
|
||||||
|
for attributeName, attributeConfig of elementGroup
|
||||||
|
if attributeConfig.config && attributeConfig.config.display
|
||||||
|
displayName = App.i18n.translateInline(attributeConfig.config.display)
|
||||||
|
else
|
||||||
|
displayName = App.i18n.translateInline(attributeName)
|
||||||
|
optgroup.append("<option value=\"#{groupKey}.#{attributeName}\">#{displayName}</option>")
|
||||||
|
selection
|
||||||
|
|
||||||
|
@rebuildAttributeSelectors: (elementFull, elementRow, groupAndAttribute) ->
|
||||||
|
|
||||||
|
# enable all
|
||||||
|
elementFull.find('.js-attributeSelector select option').removeAttr('disabled')
|
||||||
|
|
||||||
|
# disable all used attributes
|
||||||
|
elementFull.find('.js-attributeSelector select').each(->
|
||||||
|
keyLocal = $(@).val()
|
||||||
|
elementFull.find('.js-attributeSelector select option[value="' + keyLocal + '"]').attr('disabled', true)
|
||||||
|
elementFull.find('.js-hiddenAttribute').val(keyLocal)
|
||||||
|
)
|
||||||
|
|
||||||
|
# disable - if we only have one attribute
|
||||||
|
if elementFull.find('.js-attributeSelector select').length > 1
|
||||||
|
elementFull.find('.js-remove').removeClass('is-disabled')
|
||||||
|
else
|
||||||
|
elementFull.find('.js-remove').addClass('is-disabled')
|
||||||
|
|
||||||
|
# set attribute
|
||||||
|
if groupAndAttribute
|
||||||
|
elementRow.find('.js-attributeSelector select').val(groupAndAttribute)
|
||||||
|
elementRow.find('[name="condition::attribute"]').val("#{groupAndAttribute}")
|
||||||
|
|
||||||
|
@buildOperator: (elementFull, elementRow, groupAndAttribute, elements, current_operator) ->
|
||||||
|
selection = $("<select class=\"form-control\" name=\"condition::#{groupAndAttribute}::operator\"></select>")
|
||||||
|
attributeConfig = @getElementConfig(groupAndAttribute, elements)
|
||||||
|
for operator in attributeConfig.operator
|
||||||
|
operatorName = App.i18n.translateInline(operator)
|
||||||
|
selected = ''
|
||||||
|
if current_operator is operator
|
||||||
|
selected = 'selected="selected"'
|
||||||
|
selection.append("<option value=\"#{operator}\" #{selected}>#{operatorName}</option>")
|
||||||
|
selection
|
||||||
|
|
||||||
|
@rebuildOperater: (elementFull, elementRow, groupAndAttribute, elements, current_operator) ->
|
||||||
|
return if !groupAndAttribute
|
||||||
|
|
||||||
|
# do nothing if item already exists
|
||||||
|
name = "condition::#{groupAndAttribute}::operator"
|
||||||
|
return if elementRow.find("[name=\"#{name}\"]").get(0)
|
||||||
|
|
||||||
|
# render new operator
|
||||||
|
operator = @buildOperator(elementFull, elementRow, groupAndAttribute, elements, current_operator)
|
||||||
|
elementRow.find('.js-operator select').replaceWith(operator)
|
||||||
|
|
||||||
|
@humanText: (condition) ->
|
||||||
|
return [] if _.isEmpty(condition)
|
||||||
|
rules = []
|
||||||
|
for position of condition.attribute
|
||||||
|
|
||||||
|
# get stored params
|
||||||
|
groupAndAttribute = condition.attribute[position]
|
||||||
|
if condition[groupAndAttribute]
|
||||||
|
selectorExists = true
|
||||||
|
operator = condition[groupAndAttribute].operator
|
||||||
|
value = condition[groupAndAttribute].value
|
||||||
|
rules.push "Where <b>#{groupAndAttribute}</b> #{operator} <b>#{value}</b>."
|
||||||
|
rules
|
|
@ -1,27 +1,119 @@
|
||||||
class Index extends App.ControllerContent
|
class Index extends App.ControllerContent
|
||||||
|
events:
|
||||||
|
'click .js-new': 'new'
|
||||||
|
'click .js-edit': 'edit'
|
||||||
|
'click .js-delete': 'delete'
|
||||||
|
'click .js-description': 'description'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
# check authentication
|
# check authentication
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
new App.ControllerGenericIndex(
|
@load()
|
||||||
el: @el
|
#@subscribeId = App.Calendar.subscribe(@render)
|
||||||
id: @id
|
|
||||||
genericObject: 'Sla'
|
load: =>
|
||||||
|
@ajax(
|
||||||
|
id: 'sla_index'
|
||||||
|
type: 'GET'
|
||||||
|
url: @apiPath + '/slas'
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# load assets
|
||||||
|
App.Collection.loadAssets(data.assets)
|
||||||
|
|
||||||
|
@render(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
slas = App.Sla.search(
|
||||||
|
sortBy: 'name'
|
||||||
|
)
|
||||||
|
for sla in slas
|
||||||
|
if sla.first_response_time
|
||||||
|
sla.first_response_time_in_text = @toText(sla.first_response_time)
|
||||||
|
if sla.update_time
|
||||||
|
sla.update_time_in_text = @toText(sla.update_time)
|
||||||
|
if sla.solution_time
|
||||||
|
sla.solution_time_in_text = @toText(sla.solution_time)
|
||||||
|
sla.rules = App.UiElement.ticket_selector.humanText(sla.condition)
|
||||||
|
|
||||||
|
# show description button, only if content exists
|
||||||
|
showDescription = false
|
||||||
|
if App.Sla.description
|
||||||
|
if !_.isEmpty(slas)
|
||||||
|
showDescription = true
|
||||||
|
else
|
||||||
|
description = marked(App.Sla.description)
|
||||||
|
|
||||||
|
@html App.view('sla/index')(
|
||||||
|
slas: slas
|
||||||
|
showDescription: showDescription
|
||||||
|
description: description
|
||||||
|
)
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
if @subscribeId
|
||||||
|
App.Calendar.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
new: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
new App.ControllerGenericNew(
|
||||||
pageData:
|
pageData:
|
||||||
title: 'SLA'
|
title: 'SLAs'
|
||||||
home: 'slas'
|
object: 'Sla'
|
||||||
object: 'SLA'
|
|
||||||
objects: 'SLAs'
|
objects: 'SLAs'
|
||||||
navupdate: '#slas'
|
genericObject: 'Sla'
|
||||||
notes: [
|
container: @el.closest('.content')
|
||||||
# 'SLA are ...'
|
callback: @load
|
||||||
]
|
large: true
|
||||||
buttons: [
|
)
|
||||||
{ name: 'New SLA', 'data-type': 'new', class: 'btn--success' }
|
|
||||||
]
|
edit: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
id = $(e.target).closest('.action').data('id')
|
||||||
|
new App.ControllerGenericEdit(
|
||||||
|
id: id
|
||||||
|
pageData:
|
||||||
|
title: 'SLAs'
|
||||||
|
object: 'Sla'
|
||||||
|
objects: 'SLAs'
|
||||||
|
genericObject: 'Sla'
|
||||||
|
callback: @load
|
||||||
|
container: @el.closest('.content')
|
||||||
|
large: true
|
||||||
|
)
|
||||||
|
|
||||||
|
delete: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
id = $(e.target).closest('.action').data('id')
|
||||||
|
item = App.Sla.find(id)
|
||||||
|
new App.ControllerGenericDestroyConfirm(
|
||||||
|
item: item
|
||||||
|
container: @el.closest('.content')
|
||||||
|
callback: @load
|
||||||
|
)
|
||||||
|
|
||||||
|
description: (e) =>
|
||||||
|
new App.ControllerGenericDescription(
|
||||||
|
description: App.Calendar.description
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
toText: (m) ->
|
||||||
|
m = parseInt(m)
|
||||||
|
return if !m
|
||||||
|
minutes = m % 60
|
||||||
|
hours = Math.floor(m / 60)
|
||||||
|
|
||||||
|
if minutes < 10
|
||||||
|
minutes = "0#{minutes}"
|
||||||
|
if hours < 10
|
||||||
|
hours = "0#{hours}"
|
||||||
|
|
||||||
|
"#{hours}:#{minutes}"
|
||||||
|
|
||||||
App.Config.set( 'Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
App.Config.set( 'Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
|
@ -2,7 +2,7 @@ class Index extends App.Controller
|
||||||
elements:
|
elements:
|
||||||
'.js-search': 'searchInput'
|
'.js-search': 'searchInput'
|
||||||
events:
|
events:
|
||||||
'click [data-type="new"]': 'new'
|
'click [data-type=new]': 'new'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
|
@ -6,8 +6,9 @@ class App.Organization extends App.Model
|
||||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, info: true },
|
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, info: true },
|
||||||
{ name: 'shared', display: 'Shared organization', tag: 'boolean', note: 'Customers in the organization can view each other items.', type: 'boolean', default: true, null: false, info: false },
|
{ name: 'shared', display: 'Shared organization', tag: 'boolean', note: 'Customers in the organization can view each other items.', type: 'boolean', default: true, null: false, info: false },
|
||||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, info: true },
|
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, info: true },
|
||||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1, info: false },
|
|
||||||
{ name: 'active', display: 'Active', tag: 'active', default: true, info: false },
|
{ name: 'active', display: 'Active', tag: 'active', default: true, info: false },
|
||||||
|
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1, info: false },
|
||||||
|
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1, info: false },
|
||||||
]
|
]
|
||||||
@configure_overview = [
|
@configure_overview = [
|
||||||
'name',
|
'name',
|
||||||
|
|
|
@ -4,11 +4,9 @@ class App.Sla extends App.Model
|
||||||
@url: @apiPath + '/slas'
|
@url: @apiPath + '/slas'
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||||
{ name: 'first_response_time', display: 'First Response Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
{ name: 'condition', display: 'Selector', tag: 'ticket_selector', null: false, note: 'Create rules that single out the tickets for the Service Level Agreement.' },
|
||||||
{ name: 'update_time', display: 'Update Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
|
||||||
{ name: 'close_time', display: 'Solution Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
|
||||||
{ name: 'calendar_id', display: 'Calendar', tag: 'select', relation: 'Calendar', null: false },
|
{ name: 'calendar_id', display: 'Calendar', tag: 'select', relation: 'Calendar', null: false },
|
||||||
{ name: 'condition', display: 'Conditions where SLA is used', tag: 'ticket_attribute_selection', null: true },
|
{ name: 'sla_times', display: 'SLA Times', tag: 'sla_times', null: true },
|
||||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||||
|
|
|
@ -5,7 +5,7 @@ class App.Ticket extends App.Model
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
{ name: 'number', display: '#', tag: 'input', type: 'text', limit: 100, null: true, read_only: true, style: 'width: 60px' },
|
{ name: 'number', display: '#', tag: 'input', type: 'text', limit: 100, null: true, read_only: true, style: 'width: 60px' },
|
||||||
{ name: 'customer_id', display: 'Customer', tag: 'input', type: 'text', limit: 100, null: false, autocapitalize: false, relation: 'User' },
|
{ name: 'customer_id', display: 'Customer', tag: 'input', type: 'text', limit: 100, null: false, autocapitalize: false, relation: 'User' },
|
||||||
{ name: 'organization_id', display: 'Organization', relation: 'Organization', tagreadonly: 1 },
|
{ name: 'organization_id', display: 'Organization', tag: 'select', relation: 'Organization', tagreadonly: 1 },
|
||||||
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, limit: 100, null: false, relation: 'Group', style: 'width: 10%', edit: true },
|
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, limit: 100, null: false, relation: 'Group', style: 'width: 10%', edit: true },
|
||||||
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, limit: 100, null: true, relation: 'User', style: 'width: 12%', edit: true },
|
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, limit: 100, null: true, relation: 'User', style: 'width: 12%', edit: true },
|
||||||
{ name: 'title', display: 'Title', tag: 'input', type: 'text', limit: 100, null: false, parentClass: 'noTruncate' },
|
{ name: 'title', display: 'Title', tag: 'input', type: 'text', limit: 100, null: false, parentClass: 'noTruncate' },
|
||||||
|
|
|
@ -23,6 +23,7 @@ class App.User extends App.Model
|
||||||
{ name: 'role_ids', display: 'Roles', tag: 'checkbox', multiple: true, null: false, relation: 'Role' },
|
{ name: 'role_ids', display: 'Roles', tag: 'checkbox', multiple: true, null: false, relation: 'Role' },
|
||||||
{ name: 'group_ids', display: 'Groups', tag: 'checkbox', multiple: true, null: true, relation: 'Group', invite_agent: true },
|
{ name: 'group_ids', display: 'Groups', tag: 'checkbox', multiple: true, null: true, relation: 'Group', invite_agent: true },
|
||||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||||
|
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||||
]
|
]
|
||||||
@configure_overview = [
|
@configure_overview = [
|
||||||
|
|
|
@ -26,25 +26,25 @@
|
||||||
<%- @T('Business Hours') %>:<br>
|
<%- @T('Business Hours') %>:<br>
|
||||||
<table class="table table-fluid">
|
<table class="table table-fluid">
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Monday') %></td><td><% if _.isEmpty(calendar.business_hours['mon']): %>-<% else: %><% for from, till of calendar.business_hours['mon']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Monday') %></td><td><% if _.isEmpty(calendar.business_hours['mon']): %>-<% else: %><% for from, till of calendar.business_hours['mon']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Tuesday') %></td><td><% if _.isEmpty(calendar.business_hours['tue']): %>-<% else: %><% for from, till of calendar.business_hours['tue']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Tuesday') %></td><td><% if _.isEmpty(calendar.business_hours['tue']): %>-<% else: %><% for from, till of calendar.business_hours['tue']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Wednesday') %></td><td><% if _.isEmpty(calendar.business_hours['wed']): %>-<% else: %><% for from, till of calendar.business_hours['wed']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Wednesday') %></td><td><% if _.isEmpty(calendar.business_hours['wed']): %>-<% else: %><% for from, till of calendar.business_hours['wed']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Thursday') %></td><td><% if _.isEmpty(calendar.business_hours['thu']): %>-<% else: %><% for from, till of calendar.business_hours['thu']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Thursday') %></td><td><% if _.isEmpty(calendar.business_hours['thu']): %>-<% else: %><% for from, till of calendar.business_hours['thu']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Friday') %></td><td><% if _.isEmpty(calendar.business_hours['fri']): %>-<% else: %><% for from, till of calendar.business_hours['fri']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Friday') %></td><td><% if _.isEmpty(calendar.business_hours['fri']): %>-<% else: %><% for from, till of calendar.business_hours['fri']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Saturday') %></td><td><% if _.isEmpty(calendar.business_hours['sat']): %>-<% else: %><% for from, till of calendar.business_hours['sat']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Saturday') %></td><td><% if _.isEmpty(calendar.business_hours['sat']): %>-<% else: %><% for from, till of calendar.business_hours['sat']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T('Sunday') %></td><td><% if _.isEmpty(calendar.business_hours['sun']): %>-<% else: %><% for from, till of calendar.business_hours['sun']: %><%= from %>:<%= till %> </td><td><% end %><% end %></td>
|
<td><%- @T('Sunday') %></td><td><% if _.isEmpty(calendar.business_hours['sun']): %>-<% else: %><% for from, till of calendar.business_hours['sun']: %><%= from %>-<%= till %> </td><td><% end %><% end %></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,7 +48,28 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password}
|
||||||
|
|
||||||
def index
|
def index
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
model_index_render(Sla, params)
|
|
||||||
|
assets = {}
|
||||||
|
|
||||||
|
# calendars
|
||||||
|
calendar_ids = []
|
||||||
|
Calendar.all.each {|calendar|
|
||||||
|
calendar_ids.push calendar.id
|
||||||
|
assets = calendar.assets(assets)
|
||||||
|
}
|
||||||
|
|
||||||
|
# slas
|
||||||
|
sla_ids = []
|
||||||
|
Sla.all.each {|sla|
|
||||||
|
sla_ids.push sla.id
|
||||||
|
assets = sla.assets(assets)
|
||||||
|
}
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
calendar_ids: calendar_ids,
|
||||||
|
sla_ids: sla_ids,
|
||||||
|
assets: assets,
|
||||||
|
}, status: :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ManageTest < TestCase
|
||||||
sla_create(
|
sla_create(
|
||||||
data: {
|
data: {
|
||||||
name: 'some sla' + random,
|
name: 'some sla' + random,
|
||||||
first_response_time: 61
|
first_response_time_in_text: '1:01'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
watch_for(
|
watch_for(
|
||||||
|
@ -54,7 +54,7 @@ class ManageTest < TestCase
|
||||||
)
|
)
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
click( css: '.table-overview tr:last-child td' )
|
click( css: '.content:not(.hide) .action:last-child .js-edit' )
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
set(
|
set(
|
||||||
|
@ -62,8 +62,8 @@ class ManageTest < TestCase
|
||||||
value: 'some sla update ' + random,
|
value: 'some sla update ' + random,
|
||||||
)
|
)
|
||||||
set(
|
set(
|
||||||
css: '.modal input[name="first_response_time"]',
|
css: '.modal input[name="first_response_time_in_text"]',
|
||||||
value: 121,
|
value: '2:01',
|
||||||
)
|
)
|
||||||
click( css: '.modal button.js-submit' )
|
click( css: '.modal button.js-submit' )
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class ManageTest < TestCase
|
||||||
)
|
)
|
||||||
sleep 4
|
sleep 4
|
||||||
|
|
||||||
click( css: '[data-type="destroy"]:last-child' )
|
click( css: '.content:not(.hide) .action:last-child .js-delete' )
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
click( css: '.modal button.js-submit' )
|
click( css: '.modal button.js-submit' )
|
||||||
|
|
|
@ -1577,7 +1577,7 @@ wait untill text in selector disabppears
|
||||||
:browser => browser2,
|
:browser => browser2,
|
||||||
:data => {
|
:data => {
|
||||||
:name => 'some sla' + random,
|
:name => 'some sla' + random,
|
||||||
:first_response_time => 61
|
:first_response_time_in_text => 61
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1592,14 +1592,14 @@ wait untill text in selector disabppears
|
||||||
instance.find_elements( { css: 'a[href="#manage"]' } )[0].click
|
instance.find_elements( { css: 'a[href="#manage"]' } )[0].click
|
||||||
instance.find_elements( { css: 'a[href="#manage/slas"]' } )[0].click
|
instance.find_elements( { css: 'a[href="#manage/slas"]' } )[0].click
|
||||||
sleep 2
|
sleep 2
|
||||||
instance.find_elements( { css: 'a[data-type="new"]' } )[0].click
|
instance.find_elements( { css: 'a.js-new' } )[0].click
|
||||||
sleep 2
|
sleep 2
|
||||||
element = instance.find_elements( { css: '.modal input[name=name]' } )[0]
|
element = instance.find_elements( { css: '.modal input[name=name]' } )[0]
|
||||||
element.clear
|
element.clear
|
||||||
element.send_keys( data[:name] )
|
element.send_keys( data[:name] )
|
||||||
element = instance.find_elements( { css: '.modal input[name=first_response_time]' } )[0]
|
element = instance.find_elements( { css: '.modal input[name=first_response_time_in_text]' } )[0]
|
||||||
element.clear
|
element.clear
|
||||||
element.send_keys( data[:first_response_time] )
|
element.send_keys( data[:first_response_time_in_text] )
|
||||||
instance.find_elements( { css: '.modal button.js-submit' } )[0].click
|
instance.find_elements( { css: '.modal button.js-submit' } )[0].click
|
||||||
(1..8).each {
|
(1..8).each {
|
||||||
element = instance.find_elements( { css: 'body' } )[0]
|
element = instance.find_elements( { css: 'body' } )[0]
|
||||||
|
|
Loading…
Reference in a new issue