Introduced new @P() to print values in templates based on attribute definition.
This commit is contained in:
parent
0d216b3bc6
commit
64794c3767
39 changed files with 409 additions and 247 deletions
|
@ -369,7 +369,7 @@ class App.Controller extends Spine.Controller
|
|||
|
||||
userTicketPopups: (params) ->
|
||||
|
||||
show = (data, tickets) =>
|
||||
show = (data, ticket_list) =>
|
||||
|
||||
if !data.position
|
||||
data.position = 'left'
|
||||
|
@ -390,15 +390,14 @@ class App.Controller extends Spine.Controller
|
|||
|
||||
content: ->
|
||||
type = $(@).filter('[data-type]').data('type')
|
||||
data = tickets[type] || []
|
||||
|
||||
# set human time
|
||||
for ticket in data
|
||||
ticket.humanTime = controller.humanTime(ticket.created_at)
|
||||
tickets = []
|
||||
if ticket_list[type]
|
||||
for ticket_id in ticket_list[type]
|
||||
tickets.push App.Ticket.fullLocal( ticket_id )
|
||||
|
||||
# insert data
|
||||
App.view('popover/user_ticket_list')(
|
||||
tickets: data,
|
||||
tickets: tickets,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -411,14 +410,18 @@ class App.Controller extends Spine.Controller
|
|||
}
|
||||
processData: true,
|
||||
success: (data, status, xhr) =>
|
||||
App.Store.write( "user-ticket-popover::#{params.user_id}", data.tickets )
|
||||
show( params, data.tickets )
|
||||
App.Store.write( "user-ticket-popover::#{params.user_id}", data )
|
||||
|
||||
# load assets
|
||||
App.Collection.loadAssets( data.assets )
|
||||
|
||||
show( params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed } )
|
||||
)
|
||||
|
||||
# get data
|
||||
tickets = App.Store.get( "user-ticket-popover::#{params.user_id}" )
|
||||
if tickets
|
||||
show( params, tickets )
|
||||
data = App.Store.get( "user-ticket-popover::#{params.user_id}" )
|
||||
if data
|
||||
show( params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed } )
|
||||
@delay(
|
||||
=>
|
||||
fetch(params)
|
||||
|
|
|
@ -82,7 +82,7 @@ class App.ControllerTable extends App.Controller
|
|||
el: element
|
||||
overview: ['time', 'area', 'level', 'browser', 'location', 'data']
|
||||
attributes: [
|
||||
{ name: 'time', display: 'Time', type: 'time' },
|
||||
{ name: 'time', display: 'Time', tag: 'datetime' },
|
||||
{ name: 'area', display: 'Area', type: 'text' },
|
||||
{ name: 'level', display: 'Level', type: 'text' },
|
||||
{ name: 'browser', display: 'Browser', type: 'text' },
|
||||
|
|
|
@ -156,11 +156,8 @@ class App.Navigation extends App.Controller
|
|||
area.result = []
|
||||
for id in area.ids
|
||||
ticket = App.Ticket.find( id )
|
||||
ticket.humanTime = @humanTime(ticket.created_at)
|
||||
data =
|
||||
display: "##{ticket.number} - #{ticket.title}"
|
||||
createt_at: "#{ticket.created_at}"
|
||||
humanTime: "#{ticket.humanTime}"
|
||||
id: ticket.id
|
||||
class: "task level-1 ticket-popover"
|
||||
url: ticket.uiUrl()
|
||||
|
|
|
@ -10,29 +10,111 @@
|
|||
#= require_tree ./lib/app_post
|
||||
|
||||
class App extends Spine.Controller
|
||||
@viewPrint: (object, attribute_name) ->
|
||||
attributes = {}
|
||||
if object.constructor.attributesGet
|
||||
attributes = object.constructor.attributesGet()
|
||||
attribute_config = attributes[attribute_name]
|
||||
value = object[attribute_name]
|
||||
valueRef = undefined
|
||||
|
||||
# check if relation is requested
|
||||
if !attribute_config
|
||||
attribute_name_new = "#{attribute_name}_id"
|
||||
attribute_config = attributes[attribute_name_new]
|
||||
if attribute_config
|
||||
attribute_name = attribute_name_new
|
||||
if object[attribute_name]
|
||||
valueRef = value
|
||||
value = object[attribute_name]
|
||||
|
||||
# in case of :: key, get the sub value
|
||||
if !value
|
||||
parts = attribute_name.split('::')
|
||||
if parts[0] && parts[1] && object[ parts[0] ]
|
||||
value = object[ parts[0] ][ parts[1] ]
|
||||
|
||||
#console.log('Pa', attribute_name, object, attribute_config, object[attribute_name], valueRef, value)
|
||||
|
||||
# if we have no config, get output this way
|
||||
if !attribute_config
|
||||
return @viewPrintItem( value )
|
||||
|
||||
# check if valueRef already exists, no lookup needed later
|
||||
if !valueRef
|
||||
attribute_name_without_ref = attribute_name.substr(attribute_name.length-3, attribute_name.length)
|
||||
if attribute_name_without_ref is '_id'
|
||||
attribute_name_without_ref = attribute_name.substr(0, attribute_name.length-3)
|
||||
if object[attribute_name_without_ref]
|
||||
valueRef = object[attribute_name_without_ref]
|
||||
|
||||
return @viewPrintItem( value, attribute_config, valueRef )
|
||||
|
||||
# define print name helper
|
||||
@viewPrintItem: ( item, attribute_config = {}, valueRef ) ->
|
||||
return '-' if item is undefined
|
||||
return '-' if item is ''
|
||||
return item if !item
|
||||
result = item
|
||||
|
||||
# lookup relation
|
||||
if attribute_config.relation || valueRef
|
||||
if valueRef
|
||||
item = valueRef
|
||||
else
|
||||
item = App[attribute_config.relation].find(item)
|
||||
|
||||
# if date is a object, get name of the object
|
||||
isObject = false
|
||||
if typeof item is 'object'
|
||||
isObject = true
|
||||
if item.displayNameLong
|
||||
result = item.displayNameLong()
|
||||
else if item.displayName
|
||||
result = item.displayName()
|
||||
else
|
||||
result = item.name
|
||||
|
||||
# execute callback on content
|
||||
if attribute_config.callback
|
||||
result = attribute_config.callback( result, attribute_config )
|
||||
|
||||
# text2html in textarea view
|
||||
if attribute_config.tag is 'textarea'
|
||||
result = App.Utils.text2html( result )
|
||||
|
||||
# fillup options
|
||||
if !_.isEmpty(attribute_config.options)
|
||||
if attribute_config.options[result]
|
||||
result = attribute_config.options[result]
|
||||
|
||||
# translate content
|
||||
isTranslated = false
|
||||
if attribute_config.translate || ( isObject && item.translate && item.translate() )
|
||||
isTranslated = true
|
||||
result = App.i18n.translateContent( result )
|
||||
|
||||
# transform date
|
||||
if attribute_config.tag is 'date'
|
||||
result = App.i18n.translateDate(result)
|
||||
|
||||
# use pretty time for datetime
|
||||
else if attribute_config.tag is 'datetime'
|
||||
result = "<span class=\"humanTimeFromNow #{attribute_config.class}\" data-time=\"#{result}\">?</span>"
|
||||
#result = App.i18n.translateTimestamp(result)
|
||||
|
||||
else if !isTranslated
|
||||
if typeof result is 'string'
|
||||
result = App.Utils.htmlEscape(result)
|
||||
|
||||
result
|
||||
|
||||
@view: (name) ->
|
||||
template = ( params = {} ) =>
|
||||
|
||||
# define print name helper
|
||||
params.P = ( item, row = {} ) ->
|
||||
return '-' if item is undefined
|
||||
return '-' if item is ''
|
||||
return item if !item
|
||||
|
||||
# if date is a object, get name of the object
|
||||
if typeof item is 'object'
|
||||
if item.displayNameLong
|
||||
return item.displayNameLong()
|
||||
else if item.displayName
|
||||
return item.displayName()
|
||||
return item.name
|
||||
|
||||
# execute callback on content
|
||||
if row.callback
|
||||
return row.callback( item, row )
|
||||
|
||||
# return raw data
|
||||
item
|
||||
params.P = ( object, attribute_name ) ->
|
||||
App.viewPrint( object, attribute_name )
|
||||
|
||||
# define date format helper
|
||||
params.date = ( time ) ->
|
||||
|
|
|
@ -4,11 +4,11 @@ class App.EmailAddress extends App.Model
|
|||
@url: @apiPath + '/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' },
|
||||
{ name: 'realname', display: 'Realname', tag: 'input', type: 'text', limit: 250, null: false },
|
||||
{ name: 'email', display: 'Email', tag: 'input', type: 'text', limit: 250, null: false },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
]
|
||||
@configure_overview = [
|
||||
'realname', 'email'
|
||||
|
|
|
@ -4,15 +4,15 @@ class App.Group extends App.Model
|
|||
@url: @apiPath + '/groups'
|
||||
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
||||
{ name: 'assignment_timeout', display: 'Assignment Timeout', tag: 'input', note: 'Assignment timeout 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 up 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: { true: 'yes', false: '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: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'assignment_timeout', display: 'Assignment Timeout', tag: 'input', note: 'Assignment timeout in minutes if assigned agent is not working on it. Ticket will be shown as unassigend.', type: 'text', limit: 100, null: true },
|
||||
{ name: 'follow_up_possible', display: 'Follow up 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.' },
|
||||
{ name: 'follow_up_assignment', display: 'Assign Follow Ups', tag: 'select', default: 'yes', options: { true: 'yes', false: 'no' }, 'null': false, note: 'Assign follow up to latest agent again.' },
|
||||
{ name: 'email_address_id', display: 'Email', tag: 'select', multiple: false, null: true, relation: 'EmailAddress', nulloption: true },
|
||||
{ name: 'signature_id', display: 'Signature', tag: 'select', multiple: false, null: true, relation: 'Signature', nulloption: true },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
]
|
||||
@configure_overview = [
|
||||
'name',
|
||||
|
|
|
@ -8,15 +8,15 @@ class App.Job extends App.Model
|
|||
{ name: 'condition', display: 'Conditions for matching objects.', tag: 'ticket_attribute_selection', null: true },
|
||||
{ name: 'execute', display: 'Execute changes on objects.', tag: 'ticket_attribute_set', null: true },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, null: false },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', default: true, null: false },
|
||||
{ name: 'matching', display: 'Matching', readonly: 1 },
|
||||
{ name: 'processed', display: 'Processed', readonly: 1 },
|
||||
{ name: 'last_run_at', display: 'Last run', type: 'time', readonly: 1 },
|
||||
{ name: 'processed', display: 'Processed', readonly: 1 },
|
||||
{ name: 'last_run_at', display: 'Last run', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'running', display: 'Running', tag: 'boolean', readonly: 1 },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -2,8 +2,8 @@ class App.Network extends App.Model
|
|||
@configure 'Network', 'name', 'note', 'active', 'updated_at'
|
||||
@extend Spine.Model.Ajax
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'xlarge' },
|
||||
{ name: 'note', display: 'Note', note: 'Notes are visible to agents only, never to customers.', tag: 'textarea', limit: 250, 'null': true, 'class': 'xlarge' },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'xlarge' },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'note', display: 'Note', note: 'Notes are visible to agents only, never to customers.', tag: 'textarea', limit: 250, null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
]
|
||||
|
|
|
@ -3,13 +3,13 @@ class App.ObjectManagerAttribute extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/object_manager_attributes'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false },
|
||||
{ name: 'display', display: 'Anzeige', tag: 'input', type: 'text', limit: 100, 'null': false },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'display', display: 'Anzeige', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'object', display: 'Object', tag: 'input', readonly: 1 },
|
||||
{ name: 'position', display: 'Position', tag: 'input', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'data_type', display: 'Format', tag: 'input', type: 'text', limit: 100, 'null': false },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', default: true, null: false },
|
||||
{ name: 'data_type', display: 'Format', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_overview = [
|
||||
#'name',
|
||||
|
|
|
@ -3,11 +3,11 @@ class App.Organization extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/organizations'
|
||||
@configure_attributes = [
|
||||
{ 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: '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', type: 'time', readonly: 1, info: false },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', 'default': true, 'null': false, info: false },
|
||||
{ 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: '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: 'boolean', default: true, null: false, info: false },
|
||||
]
|
||||
@configure_overview = [
|
||||
'name',
|
||||
|
|
|
@ -131,11 +131,11 @@ class App.Overview extends App.Model
|
|||
owner: 'Owner'
|
||||
class: 'span4'
|
||||
},
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', default: true, null: false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -8,13 +8,13 @@ class App.PostmasterFilter extends App.Model
|
|||
{ name: 'channel', display: 'Channel', type: 'input', readonly: 1 },
|
||||
{ name: 'match', display: 'Match all of the following', tag: 'postmaster_match' },
|
||||
{ name: 'perform', display: 'Perform action of the following', tag: 'postmaster_set' },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -3,13 +3,13 @@ class App.Role extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/roles'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, null: false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, null: false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_overview = [
|
||||
'name',
|
||||
|
|
|
@ -4,14 +4,14 @@ class App.Signature extends App.Model
|
|||
@url: @apiPath + '/signatures'
|
||||
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
||||
{ name: 'body', display: 'Text', tag: 'textarea', limit: 250, 'null': true, 'class': 'span4', rows: 10 },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false },
|
||||
{ name: 'body', display: 'Text', tag: 'textarea', limit: 250, 'null': true, rows: 10 },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_overview = [
|
||||
'name',
|
||||
|
|
|
@ -31,11 +31,11 @@ class App.Sla extends App.Model
|
|||
group: 'Group'
|
||||
owner: 'Owner'
|
||||
},
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', default: true, null: false },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -3,11 +3,11 @@ class App.TextModule extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/text_modules'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
||||
{ name: 'keywords', display: 'Keywords', tag: 'input', type: 'text', limit: 100, 'null': true, 'class': 'span4' },
|
||||
{ name: 'content', display: 'Content', tag: 'textarea', limit: 250, 'null': false, 'class': 'span4' },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
|
||||
{ name: 'keywords', display: 'Keywords', tag: 'input', type: 'text', limit: 100, 'null': true, 'class': 'span4' },
|
||||
{ name: 'content', display: 'Content', tag: 'textarea', limit: 250, 'null': false, 'class': 'span4' },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -11,18 +11,18 @@ class App.Ticket extends App.Model
|
|||
{ name: 'title', display: 'Title', tag: 'input', type: 'text', limit: 100, null: false, parentClass: 'noTruncate' },
|
||||
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, relation: 'TicketState', default: 'new', style: 'width: 12%', edit: true, customer: true, },
|
||||
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, relation: 'TicketPriority', default: '2 normal', style: 'width: 12%', edit: true, customer: true, },
|
||||
{ name: 'last_contact', display: 'Last contact', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'last_contact_agent', display: 'Last contact (Agent)', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'last_contact_customer', display: 'Last contact (Customer)', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'first_response', display: 'First response', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'close_time', display: 'Close time', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'pending_time', display: 'Pending Time', type: 'time', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'escalation_time', display: 'Escalation', type: 'time', null: true, style: 'width: 12%', class: 'escalation', parentClass: 'noTruncate' },
|
||||
{ name: 'article_count', display: 'Article#', style: 'width: 12%' },
|
||||
{ name: 'last_contact', display: 'Last contact', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'last_contact_agent', display: 'Last contact (Agent)', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'last_contact_customer', display: 'Last contact (Customer)', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'first_response', display: 'First response', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'close_time', display: 'Close time', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'pending_time', display: 'Pending Time', tag: 'datetime', null: true, style: 'width: 12%', parentClass: 'noTruncate' },
|
||||
{ name: 'escalation_time', display: 'Escalation', tag: 'datetime', null: true, style: 'width: 12%', class: 'escalation', parentClass: 'noTruncate' },
|
||||
{ name: 'article_count', display: 'Article#', style: 'width: 12%' },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', style: 'width: 120px', readonly: 1, parentClass: 'noTruncate' },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', style: 'width: 120px', readonly: 1, parentClass: 'noTruncate' },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', style: 'width: 120px', readonly: 1, parentClass: 'noTruncate' },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', style: 'width: 120px', readonly: 1, parentClass: 'noTruncate' },
|
||||
]
|
||||
|
||||
uiUrl: ->
|
||||
|
|
|
@ -3,19 +3,19 @@ class App.TicketArticle extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/ticket_articles'
|
||||
@configure_attributes = [
|
||||
{ name: 'ticket_id', display: 'TicketID', null: false, readonly: 1, },
|
||||
{ name: 'from', display: 'From', tag: 'input', type: 'text', limit: 100, null: false, },
|
||||
{ name: 'to', display: 'To', tag: 'input', type: 'text', limit: 100, null: true, },
|
||||
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, },
|
||||
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, },
|
||||
{ name: 'body', display: 'Text', tag: 'textarea', rows: 5, limit: 100, null: false, },
|
||||
{ name: 'type_id', display: 'Type', tag: 'select', multiple: false, null: false, relation: 'TicketArticleType', default: '', class: 'medium' },
|
||||
{ name: 'sender_id', display: 'Sender', tag: 'select', multiple: false, null: false, relation: 'TicketArticleSender', default: '', class: 'medium' },
|
||||
{ name: 'internal', display: 'Visibility', tag: 'radio', default: false, null: true, options: { true: 'internal', false: 'public' }, class: 'medium' },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'ticket_id', display: 'TicketID', null: false, readonly: 1, },
|
||||
{ name: 'from', display: 'From', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'to', display: 'To', tag: 'input', type: 'text', limit: 100, null: true },
|
||||
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true },
|
||||
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true },
|
||||
{ name: 'body', display: 'Text', tag: 'textarea', rows: 5, limit: 100, null: false },
|
||||
{ name: 'type_id', display: 'Type', tag: 'select', multiple: false, null: false, relation: 'TicketArticleType', default: '' },
|
||||
{ name: 'sender_id', display: 'Sender', tag: 'select', multiple: false, null: false, relation: 'TicketArticleSender', default: '' },
|
||||
{ name: 'internal', display: 'Visibility', tag: 'radio', default: false, null: true, options: { true: 'internal', false: 'public' } },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
|
||||
uiUrl: ->
|
||||
|
|
|
@ -3,10 +3,10 @@ class App.TicketPriority extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/ticket_priorities'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, translate: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, translate: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_translate = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -3,10 +3,10 @@ class App.TicketState extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/ticket_states'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, translate: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', type: 'time', readonly: 1 },
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, translate: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', default: true, null: false },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_translate = true
|
||||
@configure_overview = [
|
||||
|
|
|
@ -5,25 +5,25 @@ class App.User extends App.Model
|
|||
|
||||
# @hasMany 'roles', 'App.Role'
|
||||
@configure_attributes = [
|
||||
{ name: 'login', display: 'Login', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', autocapitalize: false, signup: false, quick: false },
|
||||
{ name: 'firstname', display: 'Firstname', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', signup: true, info: true, invite_agent: true },
|
||||
{ name: 'lastname', display: 'Lastname', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', signup: true, info: true, invite_agent: true },
|
||||
{ name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 100, null: false, class: 'span4', signup: true, info: true, invite_agent: true },
|
||||
{ name: 'web', display: 'Web', tag: 'input', type: 'url', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'phone', display: 'Phone', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'mobile', display: 'Mobile', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'fax', display: 'Fax', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'organization_id', display: 'Organization', tag: 'select', multiple: false, nulloption: true, null: true, relation: 'Organization', class: 'span4', signup: false, info: true },
|
||||
{ name: 'department', display: 'Department', tag: 'input', type: 'text', limit: 200, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'street', display: 'Street', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'zip', display: 'Zip', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'city', display: 'City', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, info: true },
|
||||
{ name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 50, null: true, autocomplete: 'off', class: 'span4', signup: true, },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, class: 'span4', info: true },
|
||||
{ name: 'role_ids', display: 'Roles', tag: 'checkbox', multiple: true, null: false, relation: 'Role', class: 'span4' },
|
||||
{ name: 'group_ids', display: 'Groups', tag: 'checkbox', multiple: true, null: true, relation: 'Group', class: 'span4', invite_agent: true },
|
||||
{ name: 'active', display: 'Active', tag: 'boolean', default: true, null: true, class: 'span4' },
|
||||
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
|
||||
{ name: 'login', display: 'Login', tag: 'input', type: 'text', limit: 100, null: false, autocapitalize: false, signup: false, quick: false },
|
||||
{ name: 'firstname', display: 'Firstname', tag: 'input', type: 'text', limit: 100, null: false, signup: true, info: true, invite_agent: true },
|
||||
{ name: 'lastname', display: 'Lastname', tag: 'input', type: 'text', limit: 100, null: false, signup: true, info: true, invite_agent: true },
|
||||
{ name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 100, null: false, signup: true, info: true, invite_agent: true },
|
||||
{ name: 'web', display: 'Web', tag: 'input', type: 'url', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'phone', display: 'Phone', tag: 'input', type: 'phone', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'mobile', display: 'Mobile', tag: 'input', type: 'phone', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'fax', display: 'Fax', tag: 'input', type: 'phone', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'organization_id', display: 'Organization', tag: 'select', multiple: false, nulloption: true, null: true, relation: 'Organization', signup: false, info: true },
|
||||
{ name: 'department', display: 'Department', tag: 'input', type: 'text', limit: 200, null: true, signup: false, info: true },
|
||||
{ name: 'street', display: 'Street', tag: 'input', type: 'text', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'zip', display: 'Zip', tag: 'input', type: 'text', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'city', display: 'City', tag: 'input', type: 'text', limit: 100, null: true, signup: false, info: true },
|
||||
{ name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 50, null: true, autocomplete: 'off', signup: true, },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, info: true },
|
||||
{ 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: 'active', display: 'Active', tag: 'boolean', default: true, null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_overview = [
|
||||
# 'login', 'firstname', 'lastname', 'email', 'updated_at',
|
||||
|
|
|
@ -17,24 +17,24 @@
|
|||
<h3><a href="#" data-type="edit"><%= ticket.title %></a> <small><%= ticket.number %> <span class="humanTimeFromNow" data-time="<%= ticket.created_at %>">?</span></small></h3>
|
||||
<div class="row">
|
||||
<div class="span2">
|
||||
<b><%- @T( 'State' ) %></b> <%- @T( ticket.state.name ) %>
|
||||
<b><%- @T( 'State' ) %></b> <%- @P( ticket, 'state' ) %>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<b><%- @T( 'Group' ) %></b> <%= ticket.group.name %>
|
||||
<b><%- @T( 'Group' ) %></b> <%- @P( ticket, 'group' ) %>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<b><%- @T( 'Customer' ) %></b> <%= ticket.customer.displayName() %>
|
||||
<b><%- @T( 'Customer' ) %></b> <%- @P( ticket, 'customer' ) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span2">
|
||||
<b><%- @T( 'Priority' ) %></b> <%- @T( ticket.priority.name ) %>
|
||||
<b><%- @T( 'Priority' ) %></b> <%- @P( ticket, 'priority' ) %>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<b><%- @T( 'Owner' ) %></b> <%= ticket.owner.displayName() %>
|
||||
<b><%- @T( 'Owner' ) %></b> <%- @P( ticket, 'owner' ) %>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<b><%- @T( 'Organization' ) %></b> <%= @P( ticket.customer.organization ) %>
|
||||
<b><%- @T( 'Organization' ) %></b> <%- @P( ticket, 'organization' ) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,16 +29,9 @@
|
|||
<% groupLast = '' %>
|
||||
<% for object in @objects: %>
|
||||
<% if @groupBy: %>
|
||||
<% if object[@groupBy] && object[@groupBy].displayName: %>
|
||||
<% groupByName = object[@groupBy].displayName() %>
|
||||
<% if object[@groupBy].translate(): %>
|
||||
<% groupByName = @T(groupByName) %>
|
||||
<% end %>
|
||||
<% else: %>
|
||||
<% groupByName = object[@groupBy] || '-' %>
|
||||
<% end %>
|
||||
<% groupByName = @P( object, @groupBy ) %>
|
||||
<% if groupLast isnt groupByName: %>
|
||||
<tr class=""><td colspan="<%= length %>"><b><%- @P( groupByName ) %></b></td></tr>
|
||||
<tr class=""><td colspan="<%= length %>"><b><%= groupByName %></b></td></tr>
|
||||
<% groupLast = groupByName %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -56,47 +49,26 @@
|
|||
<td><input type="radio" value="<%= object.id %>" name="radio"/></td>
|
||||
<% end %>
|
||||
<% for item in @header: %>
|
||||
<% translation = false %>
|
||||
<% value = object[item.name] %>
|
||||
<% item_id = item.name.substr(item.name.length-3, item.name.length) %>
|
||||
<% if item_id is '_id' && object[ item.name.substr(0, item.name.length-3) ]: %>
|
||||
<% value = object[ item.name.substr(0, item.name.length-3) ] %>
|
||||
<% refObject = object[ item.name.substr(0, item.name.length-3) ] %>
|
||||
<% end %>
|
||||
<% if !value: %>
|
||||
<% parts = item.name.split '::' %>
|
||||
<% if parts[0] && parts[1] && object[ parts[0] ]: %>
|
||||
<% value = object[ parts[0] ][ parts[1] ] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if value && value.displayNameLong : %>
|
||||
<% translation = true %>
|
||||
<% value = value.displayNameLong() %>
|
||||
<% else if value && value.displayName : %>
|
||||
<% translation = true %>
|
||||
<% value = value.displayName() %>
|
||||
<% end %>
|
||||
<% item_clone = item %>
|
||||
<% value = @P( object, item.name ) %>
|
||||
<% if @callbacks: %>
|
||||
<% if item.name.substr(item.name.length-3, item.name.length) is '_id' && object[ item.name.substr(0, item.name.length-3) ]: %>
|
||||
<% refObject = object[ item.name.substr(0, item.name.length-3) ] %>
|
||||
<% end %>
|
||||
<% for attribute, callbacksAll of @callbacks: %>
|
||||
<% if attribute is item.name || attribute is item_id: %>
|
||||
<% if attribute is item.name: %>
|
||||
<% for callback in callbacksAll: %>
|
||||
<% value = callback( value, object, item_clone, @header, refObject ) %>
|
||||
<% value = callback( value, object, item, @header, refObject ) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% #console.log('HH', item_clone.name, item_clone.type, item_clone.translate, item_clone, object.translate(), refObject, translation) %>
|
||||
<td <% if item_clone.parentClass: %>class="<%= item_clone.parentClass %>"<% end %>>
|
||||
<% if item_clone.link: %><a href="<%- item_clone.link %>" <% if item_clone.target: %>target="<%= item_clone.target %>"<% end %>><% end %>
|
||||
<% if item_clone.translate || ( translation && !refObject && object.translate && object.translate() ) || ( translation && refObject && refObject.translate && refObject.translate() ) : %>
|
||||
<span <% if item_clone.class: %>class="<%= item_clone.class %>"<% end %>><%- @T( @P( value, item_clone ) ) %></span>
|
||||
<% else if item_clone.type is 'time': %>
|
||||
<span class="humanTimeFromNow <% if item_clone.class: %><%= item_clone.class %><% end %>" data-time="<%- object[item_clone.name] %>">?</span>
|
||||
<% else: %>
|
||||
<span <% if item_clone.class: %>class="<%= item_clone.class %>"<% end %> <% if item_clone.title: %>title="<%= item_clone.title %>"<% end %> <% if item_clone.data: %><% for data_key, data_item of item_clone.data: %>data-<%- data_key %>="<%= data_item %>" <% end %><% end %>><%= @P(value) %></span>
|
||||
<% end %>
|
||||
<% if item_clone.link: %></a><% end %>
|
||||
|
||||
<td <% if item.parentClass: %>class="<%= item.parentClass %>"<% end %>>
|
||||
|
||||
<% if item.link: %><a href="<%- item.link %>" <% if item.target: %>target="<%= item.target %>"<% end %>><% end %>
|
||||
<span <% if item.class: %>class="<%= item.class %>"<% end %> <% if item.title: %>title="<%= item.title %>"<% end %> <% if item.data: %><% for data_key, data_item of item.data: %>data-<%- data_key %>="<%= data_item %>" <% end %><% end %>><%- value %></span>
|
||||
<% if item.link: %></a><% end %>
|
||||
|
||||
</td>
|
||||
<% end %>
|
||||
<% if @destroy: %>
|
||||
|
@ -105,4 +77,4 @@
|
|||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
|
@ -17,7 +17,7 @@
|
|||
<% if @organization[row.name]: %>
|
||||
<div class="profile-detailsEntry">
|
||||
<label><%- @Ti( row.display ) %></label>
|
||||
<%- @L( @P( @organization[row.name] ) ) %>
|
||||
<%- @P( @organization, row.name ) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -4,11 +4,7 @@
|
|||
<% if @organization[row.name]: %>
|
||||
<div class="column">
|
||||
<h3><%- @T( row.display ) %></h3>
|
||||
<% if row.tag is 'richtext': %>
|
||||
<div><%- @organization[row.name] %></div>
|
||||
<% else: %>
|
||||
<div><%- @L( @P( @organization[row.name] ) ) %></div>
|
||||
<% end %>
|
||||
<div><%- @P( @organization, row.name ) %></div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -18,7 +14,7 @@
|
|||
<h3><%- @T('Members') %></h3>
|
||||
<% for user in @organization.members: %>
|
||||
<div class="person">
|
||||
<%= user.displayName() %>
|
||||
<%= user.displayName() %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -2,17 +2,17 @@
|
|||
<span class="<%- @ticket.icon() %>" title="<%- @ticket.iconTitle() %>"></span> <span class="<%- @ticket.iconTextClass() %>"><%- @ticket.iconTitle() %></span>
|
||||
</div>
|
||||
<hr>
|
||||
<h3><%- @P('Agent') %></h3>
|
||||
<h3><%- @T('Agent') %></h3>
|
||||
<div class="person">
|
||||
<%= @ticket.owner.displayName() %>
|
||||
<% if @ticket.owner.organization_id: %>
|
||||
<% if @ticket.owner.organization: %>
|
||||
<span class="organization"><%= @ticket.owner.organization.displayName() %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<h3><%- @P('Customer') %></h3>
|
||||
<h3><%- @T('Customer') %></h3>
|
||||
<div class="person">
|
||||
<%= @ticket.customer.displayName() %>
|
||||
<% if @ticket.customer.organization_id: %>
|
||||
<% if @ticket.customer.organization: %>
|
||||
<span class="organization"><%= @ticket.customer.organization.displayName() %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -20,18 +20,18 @@
|
|||
<div class="horizontal two-columns">
|
||||
<div class="column">
|
||||
<h3>#</h3>
|
||||
<div class="u-textTruncate"><%- @P( @ticket.number ) %></div>
|
||||
<div class="u-textTruncate"><%- @P( @ticket, 'number' ) %></div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3><%- @T( 'Priority' ) %></h3>
|
||||
<div class="u-textTruncate"><%- @T( @ticket.priority.name ) %></div>
|
||||
<div class="u-textTruncate"><%- @P( @ticket, 'priority' ) %></div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3><%- @T( 'Created' ) %></h3>
|
||||
<div class="u-textTruncate"><%- @P( @ticket.humanTime ) %></div>
|
||||
<div class="u-textTruncate"><%- @P( @ticket, 'created_at' ) %></div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3><%- @T( 'Group' ) %></h3>
|
||||
<div class="u-textTruncate"><%- @P( @ticket.group ) %></div>
|
||||
<div class="u-textTruncate"><%- @P( @ticket, 'group' ) %></div>
|
||||
</div>
|
||||
</div>
|
|
@ -7,11 +7,7 @@
|
|||
<% if @user[row.name]: %>
|
||||
<div class="column">
|
||||
<h3><%- @T( row.display ) %></h3>
|
||||
<% if row.tag is 'richtext': %>
|
||||
<div><%- @user[row.name] %></div>
|
||||
<% else: %>
|
||||
<div><%- @L( @P( @user[row.name] ) ) %></div>
|
||||
<% end %>
|
||||
<div><%- @P( @user, row.name ) %></div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<ul>
|
||||
<% for ticket in @tickets: %>
|
||||
<div class="customer-info"><a href="#ticket/zoom/<%= ticket.id %>" title="<%= ticket.title %>">T:<%= ticket.number %></a> <span title="<%= ticket.created_at_short %>"><%= ticket.humanTime %></span><br/><%= ticket.title %></div>
|
||||
<li><a href="#ticket/zoom/<%= ticket.id %>" title="<%= ticket.title %>">T:<%= ticket.number %></a> <span title="<%- @P( ticket, 'created_at') %>"><%- @P( ticket, 'created_at') %></span><br/><%= ticket.title %></li>
|
||||
<% end %>
|
||||
<ul>
|
|
@ -1 +1 @@
|
|||
<h1 contenteditable="true" class="ticket-title-update" data-placeholder="<%= @T('Enter Title...') %>"><%= @P( @ticket.title ) %></h1>
|
||||
<div contenteditable="true" class="ticket-title-update" data-placeholder="<%= @T('Enter Title...') %>"><%= @ticket.title %></div>
|
|
@ -18,7 +18,7 @@
|
|||
<% if @user[row.name]: %>
|
||||
<div class="profile-detailsEntry">
|
||||
<label><%- @Ti( row.display ) %></label>
|
||||
<%- @L( @P( @user[row.name] ) ) %>
|
||||
<%- @P( @user, row.name ) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="sidebar-block">
|
||||
<% if row.tag isnt 'richtext': %>
|
||||
<label><%- @T( row.display ) %></label>
|
||||
<%- @L( @P( @organization[row.name] ) ) %>
|
||||
<%- @P( @organization, row.name ) %>
|
||||
<% else: %>
|
||||
<label><%- @T( row.display ) %></label>
|
||||
<div contenteditable="true" data-name="<%= row.name %>" data-type="update-org" data-placeholder="<%- @T('Add a Note') %>"><%- @organization[row.name] %></div>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="sidebar-block">
|
||||
<% if row.tag isnt 'richtext': %>
|
||||
<label><%- @T( row.display ) %></label>
|
||||
<%- @L( @P( @user[row.name] ) ) %>
|
||||
<%- @P( @user, row.name ) %>
|
||||
<% else: %>
|
||||
<label><%- @T( row.display ) %></label>
|
||||
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%- @user[row.name] %></div>
|
||||
|
|
|
@ -714,6 +714,10 @@ textarea,
|
|||
background: none;
|
||||
}
|
||||
|
||||
textarea.form-control {
|
||||
height: 118px;
|
||||
}
|
||||
|
||||
select.form-control {
|
||||
padding-left: 10px;
|
||||
padding-right: 34px;
|
||||
|
@ -3159,14 +3163,12 @@ footer {
|
|||
padding: 0 81px;
|
||||
}
|
||||
|
||||
.ticket-title h1 {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ticket-title-update {
|
||||
@extend h1;
|
||||
white-space: normal;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.task-subline {
|
||||
|
@ -3177,7 +3179,7 @@ footer {
|
|||
.ticket-article-item {
|
||||
padding-bottom: 33px;
|
||||
position: relative;
|
||||
|
||||
|
||||
.avatar {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
|
|
@ -97,9 +97,7 @@ class TicketsController < ApplicationController
|
|||
:customer_id => params[:customer_id],
|
||||
:limit => 15,
|
||||
)
|
||||
render :json => {
|
||||
:tickets => result
|
||||
}
|
||||
render :json => result
|
||||
end
|
||||
|
||||
# GET /api/v1/ticket_history/1
|
||||
|
|
|
@ -133,8 +133,9 @@ list tickets by customer groupd in state categroie open and closed
|
|||
returns
|
||||
|
||||
result = {
|
||||
:open => tickets_open,
|
||||
:closed => tickets_closed,
|
||||
:ticket_ids_open => tickets_open,
|
||||
:ticket_ids_closed => tickets_closed,
|
||||
:assets => { ...list of assets... },
|
||||
}
|
||||
|
||||
=end
|
||||
|
@ -150,15 +151,27 @@ returns
|
|||
:customer_id => data[:customer_id],
|
||||
:state_id => state_list_open
|
||||
).limit( data[:limit] || 15 ).order('created_at DESC')
|
||||
assets = {}
|
||||
ticket_ids_open = []
|
||||
tickets_open.each {|ticket|
|
||||
ticket_ids_open.push ticket.id
|
||||
assets = ticket.assets(assets)
|
||||
}
|
||||
|
||||
tickets_closed = Ticket.where(
|
||||
:customer_id => data[:customer_id],
|
||||
:state_id => state_list_closed
|
||||
).limit( data[:limit] || 15 ).order('created_at DESC')
|
||||
ticket_ids_closed = []
|
||||
tickets_closed.each {|ticket|
|
||||
ticket_ids_closed.push ticket.id
|
||||
assets = ticket.assets(assets)
|
||||
}
|
||||
|
||||
return {
|
||||
:open => tickets_open,
|
||||
:closed => tickets_closed,
|
||||
:ticket_ids_open => ticket_ids_open,
|
||||
:ticket_ids_closed => ticket_ids_closed,
|
||||
:assets => assets,
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ Zammad::Application.routes.draw do
|
|||
match '/tests-core', :to => 'tests#core', :via => :get
|
||||
match '/tests-ui', :to => 'tests#ui', :via => :get
|
||||
match '/tests-model', :to => 'tests#model', :via => :get
|
||||
match '/tests-model-ui', :to => 'tests#model_ui', :via => :get
|
||||
match '/tests-form', :to => 'tests#form', :via => :get
|
||||
match '/tests-form-extended', :to => 'tests#form_extended', :via => :get
|
||||
match '/tests-form-validation', :to => 'tests#form_validation', :via => :get
|
||||
|
|
79
public/assets/tests/model-ui.js
Normal file
79
public/assets/tests/model-ui.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
window.onload = function() {
|
||||
|
||||
// model
|
||||
test( "model ui basic tests", function() {
|
||||
|
||||
// load ref object
|
||||
App.Collection.loadAssets({
|
||||
TicketState: {
|
||||
1: {
|
||||
name: 'new', id: 1, updated_at: "2014-11-07T23:43:08.000Z",
|
||||
},
|
||||
2: {
|
||||
name: 'open', id: 2, updated_at: "2014-11-07T23:43:08.000Z",
|
||||
},
|
||||
3: {
|
||||
name: 'closed <>&', id: 3, updated_at: "2014-11-07T23:43:08.000Z",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// create ticket
|
||||
var attribute1 = {
|
||||
name: 'date', display: 'date 1', tag: 'date', null: true
|
||||
};
|
||||
App.Ticket.configure_attributes.push( attribute1 )
|
||||
|
||||
var ticket = new App.Ticket()
|
||||
ticket.load({
|
||||
id: 1000,
|
||||
title: 'some title <>&',
|
||||
state_id: 2,
|
||||
updated_at: '2014-11-07T23:43:08.000Z',
|
||||
date: '2015-02-07',
|
||||
})
|
||||
|
||||
App.i18n.set('en')
|
||||
equal( App.viewPrint( ticket, 'id' ), 1000)
|
||||
equal( App.viewPrint( ticket, 'title' ), 'some title <>&')
|
||||
equal( App.viewPrint( ticket, 'state' ), 'open')
|
||||
equal( App.viewPrint( ticket, 'state_id' ), 'open')
|
||||
equal( App.viewPrint( ticket, 'not_existing' ), '-')
|
||||
equal( App.viewPrint( ticket, 'updated_at' ), "<span class=\"humanTimeFromNow undefined\" data-time=\"2014-11-07T23:43:08.000Z\">?</span>")
|
||||
equal( App.viewPrint( ticket, 'date' ), '2015-02-07')
|
||||
|
||||
|
||||
App.i18n.set('de')
|
||||
equal( App.viewPrint( ticket, 'id' ), 1000)
|
||||
equal( App.viewPrint( ticket, 'title' ), 'some title <>&')
|
||||
equal( App.viewPrint( ticket, 'state' ), 'offen')
|
||||
equal( App.viewPrint( ticket, 'state_id' ), 'offen')
|
||||
equal( App.viewPrint( ticket, 'not_existing' ), '-')
|
||||
equal( App.viewPrint( ticket, 'updated_at' ), "<span class=\"humanTimeFromNow undefined\" data-time=\"2014-11-07T23:43:08.000Z\">?</span>")
|
||||
equal( App.viewPrint( ticket, 'date' ), '07.02.2015')
|
||||
|
||||
App.i18n.set('en')
|
||||
ticket.state_id = 3
|
||||
equal( App.viewPrint( ticket, 'state' ), 'closed <>&')
|
||||
equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&')
|
||||
|
||||
App.i18n.set('de')
|
||||
equal( App.viewPrint( ticket, 'state' ), 'closed <>&')
|
||||
equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&')
|
||||
|
||||
// normal string
|
||||
data = {
|
||||
a: 1,
|
||||
b: 'abc',
|
||||
c: {
|
||||
displayName: function() { return "my displayName <>&" }
|
||||
},
|
||||
}
|
||||
equal( App.viewPrint( data, 'a' ), 1)
|
||||
equal( App.viewPrint( data, 'b' ), 'abc')
|
||||
equal( App.viewPrint( data, 'c' ), 'my displayName <>&')
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
|
@ -410,14 +410,13 @@ test( "table test 2", function() {
|
|||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'true', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'true', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'true', 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2')
|
||||
equal( el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2')
|
||||
});
|
||||
|
||||
|
|
|
@ -68,6 +68,28 @@ class AAbUnitTest < TestCase
|
|||
]
|
||||
browser_single_test(tests)
|
||||
end
|
||||
def test_model_ui
|
||||
tests = [
|
||||
{
|
||||
:name => 'start',
|
||||
:instance => browser_instance,
|
||||
:url => browser_url + '/tests-model-ui',
|
||||
:action => [
|
||||
{
|
||||
:execute => 'wait',
|
||||
:value => 8,
|
||||
},
|
||||
{
|
||||
:execute => 'match',
|
||||
:css => '.result .failed',
|
||||
:value => '0',
|
||||
:match_result => true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
browser_single_test(tests)
|
||||
end
|
||||
def test_form
|
||||
tests = [
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue