Init version of object manager.

This commit is contained in:
Martin Edenhofer 2014-09-10 01:42:20 +02:00
parent 0f1eb5dd55
commit c4c4ef35ef
30 changed files with 2119 additions and 416 deletions

View file

@ -2,7 +2,11 @@ class App.ControllerForm extends App.Controller
constructor: (params) -> constructor: (params) ->
for key, value of params for key, value of params
@[key] = value @[key] = value
@attribute_count = 0
if !@handlers
@handlers = []
@handlers.push @_showHideToggle
@handlers.push @_requiredMandantoryToggle
if !@form if !@form
@form = @formGen() @form = @formGen()
@ -23,37 +27,62 @@ class App.ControllerForm extends App.Controller
fieldset = $('<fieldset></fieldset>') fieldset = $('<fieldset></fieldset>')
for attribute_clean in @model.configure_attributes # collect form attributes
attribute = _.clone( attribute_clean ) @attributes = []
if @model.attributesGet
attributesClean = @model.attributesGet(@screen)
else
attributesClean = App.Model.attributesGet(@screen, @model.configure_attributes )
if !attribute.readonly && ( !@required || @required && attribute[@required] ) for attributeName, attribute of attributesClean
@attribute_count = @attribute_count + 1 # ignore read only attributes
if !attribute.readonly
# add item # check generic filter
item = @formGenItem( attribute, @model.className, fieldset ) if @filter && !attribute.filter
item.appendTo(fieldset) if @filter[ attributeName ]
attribute.filter = @filter[ attributeName ]
# if password, add confirm password item @attributes.push attribute
if attribute.type is 'password'
# set selected value passed on current params attribute_count = 0
if @params className = @model.className + '_' + Math.floor( Math.random() * 999999 ).toString()
if attribute.name of @params
attribute.value = @params[attribute.name]
# rename display and name to _confirm for attribute in @attributes
if !attribute.single attribute_count = attribute_count + 1
attribute.display = attribute.display + ' (confirm)'
attribute.name = attribute.name + '_confirm'; # add item
item = @formGenItem( attribute, @model.className, fieldset ) item = @formGenItem( attribute, className, fieldset, attribute_count )
item.appendTo(fieldset) item.appendTo(fieldset)
# if password, add confirm password item
if attribute.type is 'password'
# set selected value passed on current params
if @params
if attribute.name of @params
attribute.value = @params[attribute.name]
# rename display and name to _confirm
if !attribute.single
attribute.display = attribute.display + ' (confirm)'
attribute.name = attribute.name + '_confirm';
item = @formGenItem( attribute, className, fieldset, attribute_count )
item.appendTo(fieldset)
if @fullForm if @fullForm
if !@formClass if !@formClass
@formClass = '' @formClass = ''
fieldset = $('<form class="' + @formClass + '"><button class="btn">' + App.i18n.translateContent('Submit') + '</button></form>').prepend( fieldset ) fieldset = $('<form class="' + @formClass + '"><button class="btn">' + App.i18n.translateContent('Submit') + '</button></form>').prepend( fieldset )
# bind form events
if @events
for eventSelector, callback of @events
do (eventSelector, callback) =>
evs = eventSelector.split(' ')
fieldset.find( evs[1] ).bind(evs[0], (e) => callback(e) )
# return form # return form
return fieldset return fieldset
@ -131,14 +160,14 @@ class App.ControllerForm extends App.Controller
### ###
formGenItem: (attribute_config, classname, form ) -> formGenItem: (attribute_config, classname, form, attribute_count ) ->
attribute = _.clone( attribute_config ) attribute = clone( attribute_config )
# create item id # create item id
attribute.id = classname + '_' + attribute.name attribute.id = classname + '_' + attribute.name
# set autofocus # set autofocus
if @autofocus && @attribute_count is 1 if @autofocus && attribute_count is 1
attribute.autofocus = 'autofocus' attribute.autofocus = 'autofocus'
# set required option # set required option
@ -234,6 +263,22 @@ class App.ControllerForm extends App.Controller
else if attribute.tag is 'select' else if attribute.tag is 'select'
item = $( App.view('generic/select')( attribute: attribute ) ) item = $( App.view('generic/select')( attribute: attribute ) )
# date
else if attribute.tag is 'date'
attribute.type = 'text'
item = $( App.view('generic/date')( attribute: attribute ) )
#item.datetimepicker({
# format: 'Y.m.d'
#});
# date
else if attribute.tag is 'datetime'
attribute.type = 'text'
item = $( App.view('generic/date')( attribute: attribute ) )
#item.datetimepicker({
# format: 'Y.m.d H:i'
#});
# timezone # timezone
else if attribute.tag is 'timezone' else if attribute.tag is 'timezone'
attribute.options = [] attribute.options = []
@ -717,7 +762,7 @@ class App.ControllerForm extends App.Controller
b = (event, item) => b = (event, item) =>
# set html form attribute # set html form attribute
$(local_attribute).val(item.id) $(local_attribute).val(item.id).trigger('change')
$(local_attribute + '_autocompletion_value_shown').val(item.value) $(local_attribute + '_autocompletion_value_shown').val(item.value)
# call calback # call calback
@ -738,8 +783,11 @@ class App.ControllerForm extends App.Controller
} }
) )
### ###
source = attribute.source
if typeof(source) is 'string'
source = source.replace('#{@apiPath}', App.Config.get('api_path') );
$(local_attribute_full).autocomplete( $(local_attribute_full).autocomplete(
source: attribute.source, source: source,
minLength: attribute.minLengt || 3, minLength: attribute.minLengt || 3,
select: ( event, ui ) => select: ( event, ui ) =>
b(event, ui.item) b(event, ui.item)
@ -1221,63 +1269,12 @@ class App.ControllerForm extends App.Controller
else else
item = $( App.view('generic/input')( attribute: attribute ) ) item = $( App.view('generic/input')( attribute: attribute ) )
if attribute.onchange if @handlers
if typeof attribute.onchange is 'function' item.bind('change', (e) =>
attribute.onchange(attribute) params = App.ControllerForm.params( $(e.target) )
else for handler in @handlers
for i of attribute.onchange handler(params, attribute, @attributes, classname, form, @)
a = i.split(/__/) )
if a[1]
if a[0] is attribute.name
@attribute = attribute
@classname = classname
@attributes_clean = attributes_clean
@change = a
b = =>
# console.log 'aaa', @attribute
attribute = @attribute
change = @change
classname = @classname
attributes_clean = @attributes_clean
ui = @
$( '#' + @attribute.id ).bind('change', ->
ui.log 'change', @, attribute, change
ui.log change[0] + ' has changed - changing ' + change[1]
item = $( ui.formGenItem(attribute, classname, attributes_clean) )
ui.log item, classname
)
App.Delay.set( b, 100, undefined, 'form_change' )
# if attribute.onchange[]
ui = @
item.bind('change', ->
if ui.form_data
params = App.ControllerForm.params(@)
for i of ui.form_data
a = i.split(/__/)
if a[1] && a[0] is attribute.name
newListAttribute = i
changedAttribute = a[0]
toChangeAttribute = a[1]
# get new option list
newListAttributes = ui['form_data'][newListAttribute][ params['group_id'] ]
# find element to replace
for item in ui.model.configure_attributes
if item.name is toChangeAttribute
item.display = false
item['filter'][toChangeAttribute] = newListAttributes
if params[changedAttribute]
item.default = params[toChangeAttribute]
if !item.default
delete item['default']
newElement = ui.formGenItem( item, classname, form )
# replace new option list
form.find('[name="' + toChangeAttribute + '"]').replaceWith( newElement )
)
# bind dependency # bind dependency
if @dependency if @dependency
@ -1339,6 +1336,44 @@ class App.ControllerForm extends App.Controller
el.find('[name="' + key + '"]').parents('.form-group').addClass('hide') el.find('[name="' + key + '"]').parents('.form-group').addClass('hide')
el.find('[name="' + key + '"]').addClass('is-hidden') el.find('[name="' + key + '"]').addClass('is-hidden')
_mandantory: (name, el = @el) ->
if !_.isArray(name)
name = [name]
for key in name
el.find('[name="' + key + '"]').attr('required', true)
el.find('[name="' + key + '"]').parents('.form-group').find('label span').html('*')
_optional: (name, el = @el) ->
if !_.isArray(name)
name = [name]
for key in name
el.find('[name="' + key + '"]').attr('required', false)
el.find('[name="' + key + '"]').parents('.form-group').find('label span').html('')
_showHideToggle: (params, changedAttribute, attributes, classname, form, ui) =>
for attribute in attributes
if attribute.shown_if
hit = false
for refAttribute, refValue of attribute.shown_if
if params[refAttribute] && params[refAttribute].toString() is refValue.toString()
hit = true
if hit
ui._show(attribute.name)
else
ui._hide(attribute.name)
_requiredMandantoryToggle: (params, changedAttribute, attributes, classname, form, ui) =>
for attribute in attributes
if attribute.required_if
hit = false
for refAttribute, refValue of attribute.required_if
if params[refAttribute] && params[refAttribute].toString() is refValue.toString()
hit = true
if hit
ui._mandantory(attribute.name)
else
ui._optional(attribute.name)
# sort attribute.options # sort attribute.options
_sortOptions: (attribute) -> _sortOptions: (attribute) ->
@ -1399,6 +1434,7 @@ class App.ControllerForm extends App.Controller
list = [] list = []
if attribute.filter if attribute.filter
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter', attribute.filter App.Log.debug 'ControllerForm', '_getRelationOptionList:filter', attribute.filter
# function based filter # function based filter
@ -1426,6 +1462,22 @@ class App.ControllerForm extends App.Controller
if record['id'] is key if record['id'] is key
list.push record list.push record
# data based filter
else if attribute.filter && _.isArray attribute.filter
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-array', attribute.filter
# check all records
for record in App[ attribute.relation ].search( sortBy: attribute.sortBy )
# check all filter attributes
for key in attribute.filter
# check all filter values as array
# if it's matching, use it for selection
if record['id'] is key
list.push record
# no data filter matched # no data filter matched
else else
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-data no filter matched' App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-data no filter matched'
@ -1512,8 +1564,9 @@ class App.ControllerForm extends App.Controller
validate: (params) -> validate: (params) ->
App.Model.validate( App.Model.validate(
model: @model, model: @model
params: params, params: params
screen: @screen
) )
# get all params of the form # get all params of the form
@ -1637,13 +1690,8 @@ class App.ControllerForm extends App.Controller
# show new errors # show new errors
for key, msg of data.errors for key, msg of data.errors
$(data.form).parents().find('[name*="' + key + '"]').parents('div .form-group').addClass('has-error') $(data.form).parents().find('[name="' + key + '"]').parents('div .form-group').addClass('has-error')
$(data.form).parents().find('[name*="' + key + '"]').parent().find('.help-inline').html(msg) $(data.form).parents().find('[name="' + key + '"]').parent().find('.help-inline').html(msg)
# set autofocus # set autofocus
$(data.form).parents().find('.has-error').find('input, textarea').first().focus() $(data.form).parents().find('.has-error').find('input, textarea').first().focus()
# # enable form again
# if $(data.form).parents().find('.has-error').html()
# @formEnable(data.form)

View file

@ -7,11 +7,11 @@ class App.ControllerGenericNew extends App.ControllerModal
@html App.view('generic/admin/new')( head: @pageData.object ) @html App.view('generic/admin/new')( head: @pageData.object )
new App.ControllerForm( new App.ControllerForm(
el: @el.find('#object_new'), el: @el.find('#object_new')
model: App[ @genericObject ], model: App[ @genericObject ]
params: @item, params: @item
required: @required, screen: @screen || 'edit'
autofocus: true, autofocus: true
) )
@modalShow() @modalShow()
@ -59,7 +59,7 @@ class App.ControllerGenericEdit extends App.ControllerModal
el: @el.find('#object_edit') el: @el.find('#object_edit')
model: App[ @genericObject ] model: App[ @genericObject ]
params: @item params: @item
required: @required screen: @screen || 'edit'
autofocus: true autofocus: true
) )
@modalShow() @modalShow()

View file

@ -99,6 +99,7 @@ class App.ControllerTable extends App.Controller
data.model = {} data.model = {}
overview = data.overview || data.model.configure_overview || [] overview = data.overview || data.model.configure_overview || []
attributes = data.attributes || data.model.configure_attributes || {} attributes = data.attributes || data.model.configure_attributes || {}
attributes = App.Model.attributesGet(false, attributes)
destroy = data.model.configure_delete destroy = data.model.configure_delete
# check if table is empty # check if table is empty
@ -146,13 +147,13 @@ class App.ControllerTable extends App.Controller
header = [] header = []
for item in overview for item in overview
headerFound = false headerFound = false
for attribute in attributes for attributeName, attribute of attributes
if attribute.name is item if attributeName is item
headerFound = true headerFound = true
header.push attribute header.push attribute
else else
rowWithoutId = item + '_id' rowWithoutId = item + '_id'
if attribute.name is rowWithoutId if attributeName is rowWithoutId
headerFound = true headerFound = true
header.push attribute header.push attribute

View file

@ -14,7 +14,7 @@ class App.TicketCreate extends App.Controller
# set title # set title
@form_id = App.ControllerForm.formId() @form_id = App.ControllerForm.formId()
@edit_form = undefined @form_meta = undefined
# set article attributes # set article attributes
default_type = 'call_inbound' default_type = 'call_inbound'
@ -25,14 +25,17 @@ class App.TicketCreate extends App.Controller
sender: 'Customer' sender: 'Customer'
article: 'phone' article: 'phone'
title: 'Call Inbound' title: 'Call Inbound'
screen: 'create_phone_in'
call_outbound: call_outbound:
sender: 'Agent' sender: 'Agent'
article: 'phone' article: 'phone'
title: 'Call Outbound' title: 'Call Outbound'
screen: 'create_phone_out'
email: email:
sender: 'Agent' sender: 'Agent'
article: 'email' article: 'email'
title: 'Email' title: 'Email'
screen: 'create_email_out'
@article_attributes = article_sender_type_map[@type] @article_attributes = article_sender_type_map[@type]
# remember split info if exists # remember split info if exists
@ -57,9 +60,9 @@ class App.TicketCreate extends App.Controller
meta: => meta: =>
text = App.i18n.translateInline( @article_attributes['title'] ) text = App.i18n.translateInline( @article_attributes['title'] )
subject = @el.find('[name=subject]').val() title = @el.find('[name=title]').val()
if subject if title
text = "#{text}: #{subject}" text = "#{text}: #{title}"
meta = meta =
url: @url() url: @url()
head: text head: text
@ -100,7 +103,7 @@ class App.TicketCreate extends App.Controller
if cache && !params.ticket_id && !params.article_id if cache && !params.ticket_id && !params.article_id
# get edit form attributes # get edit form attributes
@edit_form = cache.edit_form @form_meta = cache.form_meta
# load assets # load assets
App.Collection.loadAssets( cache.assets ) App.Collection.loadAssets( cache.assets )
@ -108,7 +111,7 @@ class App.TicketCreate extends App.Controller
@render() @render()
else else
@ajax( @ajax(
id: 'ticket_create' id: 'ticket_create' + @task_key
type: 'GET' type: 'GET'
url: @apiPath + '/ticket_create' url: @apiPath + '/ticket_create'
data: data:
@ -121,7 +124,7 @@ class App.TicketCreate extends App.Controller
App.Store.write( 'ticket_create_attributes', data ) App.Store.write( 'ticket_create_attributes', data )
# get edit form attributes # get edit form attributes
@edit_form = data.edit_form @form_meta = data.form_meta
# load assets # load assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets( data.assets )
@ -143,22 +146,6 @@ class App.TicketCreate extends App.Controller
render: (template = {}) -> render: (template = {}) ->
# set defaults
defaults =
state_id: App.TicketState.findByAttribute( 'name', 'open' ).id
priority_id: App.TicketPriority.findByAttribute( 'name', '2 normal' ).id
# generate form
configure_attributes = [
{ name: 'customer_id', display: 'Customer', tag: 'autocompletion', type: 'text', limit: 200, null: false, relation: 'User', class: 'span7', autocapitalize: false, help: 'Select the customer of the Ticket or create one.', helpLink: '<a href="" class="customer_new">&raquo;</a>', callback: @localUserInfo, source: @apiPath + '/users/search', minLengt: 2 },
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: @edit_form, nulloption: true, relation: 'Group', default: defaults['group_id'], class: 'span7', },
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', },
{ name: 'tags', display: 'Tags', tag: 'tag', type: 'text', null: true, default: defaults['tags'], class: 'span7', },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 200, null: false, default: defaults['subject'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 8, null: false, default: defaults['body'], class: 'span7', upload: true },
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['state_id'], translate: true, class: 'medium' },
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['priority_id'], translate: true, class: 'medium' },
]
@html App.view('agent_ticket_create')( @html App.view('agent_ticket_create')(
head: 'New Ticket' head: 'New Ticket'
title: @article_attributes['title'] title: @article_attributes['title']
@ -172,14 +159,50 @@ class App.TicketCreate extends App.Controller
else if App.TaskManager.get(@task_key) && !_.isEmpty( App.TaskManager.get(@task_key).state ) else if App.TaskManager.get(@task_key) && !_.isEmpty( App.TaskManager.get(@task_key).state )
params = App.TaskManager.get(@task_key).state params = App.TaskManager.get(@task_key).state
formChanges = (params, attribute, attributes, classname, form, ui) =>
if @form_meta.dependencies && @form_meta.dependencies[attribute.name]
dependency = @form_meta.dependencies[attribute.name][ parseInt(params[attribute.name]) ]
if dependency
for fieldNameToChange of dependency
filter = []
if dependency[fieldNameToChange]
filter = dependency[fieldNameToChange]
# find element to replace
for item in attributes
if item.name is fieldNameToChange
item.display = false
item['filter'] = {}
item['filter'][ fieldNameToChange ] = filter
item.default = params[item.name]
#if !item.default
# delete item['default']
newElement = ui.formGenItem( item, classname, form )
# replace new option list
form.find('[name="' + fieldNameToChange + '"]').replaceWith( newElement )
new App.ControllerForm( new App.ControllerForm(
el: @el.find('.ticket_create') el: @el.find('.ticket-form')
form_id: @form_id form_id: @form_id
model: model: App.Ticket
configure_attributes: configure_attributes screen: @article_attributes['screen']
className: 'create_' + @type + '_' + @id events:
'change [name=customer_id]': @localUserInfo
handlers: [
formChanges
]
filter: @form_meta.filter
autofocus: true autofocus: true
form_data: @edit_form params: params
)
new App.ControllerForm(
el: @el.find('.article-form')
form_id: @form_id
model: App.TicketArticle
screen: @article_attributes['screen']
params: params params: params
) )
@ -193,20 +216,23 @@ class App.TicketCreate extends App.Controller
# show text module UI # show text module UI
@textModule = new App.WidgetTextModule( @textModule = new App.WidgetTextModule(
el: @el.find('.ticket-create').find('textarea') el: @el.find('form').find('textarea')
) )
# start auto save # start auto save
@autosave() @autosave()
localUserInfo: (params) => localUserInfo: (e) =>
params = App.ControllerForm.params( $(e.target).closest('form') )
# update text module UI # update text module UI
callback = (user) => callback = (user) =>
@textModule.reload( if @textModule
ticket: @textModule.reload(
customer: user ticket:
) customer: user
)
@userInfo( @userInfo(
user_id: params.customer_id user_id: params.customer_id
@ -234,7 +260,7 @@ class App.TicketCreate extends App.Controller
params.title = params.subject params.title = params.subject
# create ticket # create ticket
object = new App.Ticket ticket = new App.Ticket
# find sender_id # find sender_id
sender = App.TicketArticleSender.findByAttribute( 'name', @article_attributes['sender'] ) sender = App.TicketArticleSender.findByAttribute( 'name', @article_attributes['sender'] )
@ -248,6 +274,7 @@ class App.TicketCreate extends App.Controller
params['article'] = { params['article'] = {
to: (group && group.name) || '' to: (group && group.name) || ''
from: params.customer_id_autocompletion from: params.customer_id_autocompletion
cc: params.cc
subject: params.subject subject: params.subject
body: params.body body: params.body
type_id: type.id type_id: type.id
@ -258,6 +285,7 @@ class App.TicketCreate extends App.Controller
params['article'] = { params['article'] = {
from: (group && group.name) || '' from: (group && group.name) || ''
to: params.customer_id_autocompletion to: params.customer_id_autocompletion
cc: params.cc
subject: params.subject subject: params.subject
body: params.body body: params.body
type_id: type.id type_id: type.id
@ -265,15 +293,30 @@ class App.TicketCreate extends App.Controller
form_id: @form_id form_id: @form_id
} }
object.load(params) ticket.load(params)
# validate form # validate form
errors = object.validate() ticketErrors = ticket.validate(
screen: @article_attributes['screen']
)
article = new App.TicketArticle
article.load(params['article'])
articleErrors = article.validate(
screen: @article_attributes['screen']
)
for key, value of articleErrors
if !ticketErrors
ticketErrors = {}
ticketErrors[key] = value
# show errors in form # show errors in form
if errors if ticketErrors
@log 'error', errors @log 'error', ticketErrors
@formValidate( form: e.target, errors: errors ) @formValidate(
form: e.target
errors: ticketErrors
screen: @article_attributes['screen']
)
# save ticket, create article # save ticket, create article
else else
@ -281,7 +324,7 @@ class App.TicketCreate extends App.Controller
# disable form # disable form
@formDisable(e) @formDisable(e)
ui = @ ui = @
object.save( ticket.save(
done: -> done: ->
# notify UI # notify UI
@ -322,10 +365,10 @@ class UserNew extends App.ControllerModal
@html App.view('agent_user_create')( head: 'New User' ) @html App.view('agent_user_create')( head: 'New User' )
new App.ControllerForm( new App.ControllerForm(
el: @el.find('#form-user'), el: @el.find('#form-user')
model: App.User, model: App.User
required: 'quick', screen: 'edit'
autofocus: true, autofocus: true
) )
@modalShow() @modalShow()

View file

@ -16,8 +16,6 @@ class Index extends App.ControllerContent
@fetch(params) @fetch(params)
@navupdate '#customer_ticket_new' @navupdate '#customer_ticket_new'
@edit_form = undefined
# get data / in case also ticket data for split # get data / in case also ticket data for split
fetch: (params) -> fetch: (params) ->
@ -26,9 +24,6 @@ class Index extends App.ControllerContent
if cache if cache
# get edit form attributes
@edit_form = cache.edit_form
# load assets # load assets
App.Collection.loadAssets( cache.assets ) App.Collection.loadAssets( cache.assets )
@ -44,9 +39,6 @@ class Index extends App.ControllerContent
# cache request # cache request
App.Store.write( 'ticket_create_attributes', data ) App.Store.write( 'ticket_create_attributes', data )
# get edit form attributes
@edit_form = data.edit_form
# load assets # load assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets( data.assets )
@ -87,25 +79,25 @@ class Index extends App.ControllerContent
return item if item && _.contains( group_ids, item.id.toString() ) return item if item && _.contains( group_ids, item.id.toString() )
) )
# generate form
configure_attributes = [
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: groupFilter, nulloption: true, relation: 'Group', default: defaults['group_id'], class: 'span7', },
# { name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: false, default: defaults['subject'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 10, null: false, default: defaults['body'], class: 'span7', upload: true },
# { name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['state_id'], translate: true, class: 'medium' },
# { name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['priority_id'], translate: true, class: 'medium' },
]
@html App.view('customer_ticket_create')( head: 'New Ticket' ) @html App.view('customer_ticket_create')( head: 'New Ticket' )
new App.ControllerForm( new App.ControllerForm(
el: @el.find('#form_create') el: @el.find('.ticket-form')
form_id: @form_id form_id: @form_id
model: model: App.Ticket
configure_attributes: configure_attributes screen: 'create_web'
className: 'create'
autofocus: true autofocus: true
form_data: @edit_form filter:
group_id: groupFilter
params: defaults
)
new App.ControllerForm(
el: @el.find('.article-form')
form_id: @form_id
model: App.TicketArticle
screen: 'create_web'
params: defaults
) )
new App.ControllerDrox( new App.ControllerDrox(
@ -128,19 +120,21 @@ class Index extends App.ControllerContent
params.customer_id = @Session.get('id') params.customer_id = @Session.get('id')
# set prio # set prio
priority = App.TicketPriority.findByAttribute( 'name', '2 normal' ) if !params.priority_id
params.priority_id = priority.id priority = App.TicketPriority.findByAttribute( 'name', '2 normal' )
params.priority_id = priority.id
# set state # set state
state = App.TicketState.findByAttribute( 'name', 'new' ) if !params.state_id
params.state_id = state.id state = App.TicketState.findByAttribute( 'name', 'new' )
params.state_id = state.id
# fillup params # fillup params
if !params.title if !params.title
params.title = params.subject params.title = params.subject
# create ticket # create ticket
object = new App.Ticket ticket = new App.Ticket
@log 'CustomerTicketCreate', 'notice', 'updateAttributes', params @log 'CustomerTicketCreate', 'notice', 'updateAttributes', params
# find sender_id # find sender_id
@ -160,16 +154,27 @@ class Index extends App.ControllerContent
form_id: @form_id form_id: @form_id
} }
object.load(params) ticket.load(params)
# validate form # validate form
errors = object.validate() ticketErrors = ticket.validate(
screen: 'create_web'
)
article = new App.TicketArticle
article.load(params['article'])
articleErrors = article.validate(
screen: 'create_web'
)
for key, value of articleErrors
if !ticketErrors
ticketErrors = {}
ticketErrors[key] = value
# show errors in form # show errors in form
if errors if ticketErrors
@log 'CustomerTicketCreate', 'error', 'can not create', errors @log 'CustomerTicketCreate', 'error', 'can not create', ticketErrors
@formValidate( form: e.target, errors: errors ) @formValidate( form: e.target, errors: ticketErrors )
# save ticket, create article # save ticket, create article
else else
@ -177,7 +182,7 @@ class Index extends App.ControllerContent
# disable form # disable form
@formDisable(e) @formDisable(e)
ui = @ ui = @
object.save( ticket.save(
done: -> done: ->
# redirect to zoom # redirect to zoom
@ -189,7 +194,4 @@ class Index extends App.ControllerContent
) )
App.Config.set( 'customer_ticket_new', Index, 'Routes' ) App.Config.set( 'customer_ticket_new', Index, 'Routes' )
#App.Config.set( 'CustomerTicketNew', { prio: 1600, parent: '', name: 'New Ticket', target: '#customer_ticket_new', role: ['Customer'] }, 'NavBar' )
App.Config.set( 'CustomerTicketNew', { prio: 8000, parent: '', name: 'New', target: '#customer_ticket_new', role: ['Customer'] }, 'NavBarRight' ) App.Config.set( 'CustomerTicketNew', { prio: 8000, parent: '', name: 'New', target: '#customer_ticket_new', role: ['Customer'] }, 'NavBarRight' )

View file

@ -32,7 +32,7 @@ class Index extends App.ControllerContent
new App.ControllerForm( new App.ControllerForm(
el: @el.find('#form-signup') el: @el.find('#form-signup')
model: App.User model: App.User
required: 'signup' screen: 'signup'
autofocus: true autofocus: true
) )

View file

@ -7,7 +7,7 @@ class App.TicketZoom extends App.Controller
@navupdate '#' @navupdate '#'
@edit_form = undefined @form_meta = undefined
@ticket_id = params.ticket_id @ticket_id = params.ticket_id
@article_id = params.article_id @article_id = params.article_id
@signature = undefined @signature = undefined
@ -111,7 +111,7 @@ class App.TicketZoom extends App.Controller
@ticket_article_ids = data.ticket_article_ids @ticket_article_ids = data.ticket_article_ids
# get edit form attributes # get edit form attributes
@edit_form = data.edit_form @form_meta = data.form_meta
# get signature # get signature
@signature = data.signature @signature = data.signature
@ -181,7 +181,7 @@ class App.TicketZoom extends App.Controller
new Edit( new Edit(
ticket: @ticket ticket: @ticket
el: @el.find('.edit') el: @el.find('.edit')
edit_form: @edit_form form_meta: @form_meta
task_key: @task_key task_key: @task_key
ui: @ ui: @
) )
@ -331,57 +331,55 @@ class Edit extends App.Controller
formChanged: !_.isEmpty( App.TaskManager.get(@task_key).state ) formChanged: !_.isEmpty( App.TaskManager.get(@task_key).state )
) )
@configure_attributes_ticket = [
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: true, relation: 'TicketState', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' },
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: true, relation: 'TicketPriority', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' },
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: true, relation: 'Group', filter: @edit_form, class: 'span2', item_class: 'pull-left' },
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, relation: 'User', filter: @edit_form, nulloption: true, class: 'span2', item_class: 'pull-left' },
]
if @isRole('Customer')
@configure_attributes_ticket = [
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: true, relation: 'TicketState', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' },
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: true, relation: 'TicketPriority', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' },
]
@configure_attributes_article = [
{ name: 'type_id', display: 'Type', tag: 'select', multiple: false, null: true, relation: 'TicketArticleType', filter: @edit_form, default: '9', translate: true, class: 'medium' },
{ name: 'internal', display: 'Visibility', tag: 'select', null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '', default: false },
{ name: 'to', display: 'To', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
# { name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'in_reply_to', display: 'In Reply to', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
]
if @isRole('Customer')
@configure_attributes_article = [
{ name: 'to', display: 'To', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
# { name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'in_reply_to', display: 'In Reply to', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
]
@form_id = App.ControllerForm.formId() @form_id = App.ControllerForm.formId()
defaults = ticket defaults = ticket.attributes()
if @isRole('Customer')
delete defaults['state_id']
delete defaults['state']
if !_.isEmpty( App.TaskManager.get(@task_key).state ) if !_.isEmpty( App.TaskManager.get(@task_key).state )
defaults = App.TaskManager.get(@task_key).state defaults = App.TaskManager.get(@task_key).state
new App.ControllerForm( formChanges = (params, attribute, attributes, classname, form, ui) =>
el: @el.find('.form-ticket-update') if @form_meta.dependencies && @form_meta.dependencies[attribute.name]
form_id: @form_id dependency = @form_meta.dependencies[attribute.name][ parseInt(params[attribute.name]) ]
model: if dependency
configure_attributes: @configure_attributes_ticket
className: 'update_ticket_' + ticket.id
params: defaults
form_data: @edit_form
)
for fieldNameToChange of dependency
filter = []
if dependency[fieldNameToChange]
filter = dependency[fieldNameToChange]
# find element to replace
for item in attributes
if item.name is fieldNameToChange
item.display = false
item['filter'] = {}
item['filter'][ fieldNameToChange ] = filter
item.default = params[item.name]
#if !item.default
# delete item['default']
newElement = ui.formGenItem( item, classname, form )
# replace new option list
form.find('[name="' + fieldNameToChange + '"]').replaceWith( newElement )
new App.ControllerForm(
el: @el.find('.form-ticket-update')
form_id: @form_id
model: App.Ticket
screen: 'edit'
handlers: [
formChanges
]
filter: @form_meta.filter
params: defaults
)
new App.ControllerForm( new App.ControllerForm(
el: @el.find('.form-article-update') el: @el.find('.form-article-update')
form_id: @form_id form_id: @form_id
model: model: App.TicketArticle
configure_attributes: @configure_attributes_article screen: 'edit'
className: 'update_ticket_' + ticket.id filter:
form_data: @edit_form type_id: [1,9,5]
params: defaults params: defaults
dependency: [ dependency: [
{ {
@ -399,13 +397,24 @@ class Edit extends App.Controller
bind: { bind: {
name: 'type_id' name: 'type_id'
relation: 'TicketArticleType' relation: 'TicketArticleType'
value: ['note', 'twitter status', 'twitter direct-message'] value: ['note', 'phone', 'twitter status']
}, },
change: { change: {
action: 'hide' action: 'hide'
name: ['to', 'cc'], name: ['to', 'cc'],
}, },
}, },
{
bind: {
name: 'type_id'
relation: 'TicketArticleType'
value: ['twitter direct-message']
},
change: {
action: 'show'
name: ['to'],
},
},
] ]
) )
@ -453,10 +462,16 @@ class Edit extends App.Controller
@autosaveStop() @autosaveStop()
params = @formParam(e.target) params = @formParam(e.target)
# get ticket
ticket = App.Ticket.fullLocal( @ticket.id ) ticket = App.Ticket.fullLocal( @ticket.id )
@log 'notice', 'update', params, ticket @log 'notice', 'update', params, ticket
# update local ticket
# create local article
# find sender_id # find sender_id
if @isRole('Customer') if @isRole('Customer')
sender = App.TicketArticleSender.findByAttribute( 'name', 'Customer' ) sender = App.TicketArticleSender.findByAttribute( 'name', 'Customer' )
@ -469,17 +484,16 @@ class Edit extends App.Controller
params.sender_id = sender.id params.sender_id = sender.id
# update ticket # update ticket
ticket_update = {} for key, value of params
for item in @configure_attributes_ticket ticket[key] = value
ticket_update[item.name] = params[item.name]
# check owner assignment # check owner assignment
if !@isRole('Customer') if !@isRole('Customer')
if !ticket_update['owner_id'] if !ticket['owner_id']
ticket_update['owner_id'] = 1 ticket['owner_id'] = 1
# check if title exists # check if title exists
if !ticket_update['title'] && !ticket.title if !ticket['title']
alert( App.i18n.translateContent('Title needed') ) alert( App.i18n.translateContent('Title needed') )
return return
@ -505,22 +519,32 @@ class Edit extends App.Controller
@autosaveStart() @autosaveStart()
return return
ticket.load( ticket_update ) # submit ticket & article
@log 'notice', 'update ticket', ticket_update, ticket @log 'notice', 'update ticket', ticket
# disable form # disable form
@formDisable(e) @formDisable(e)
# validate ticket # validate ticket
errors = ticket.validate() errors = ticket.validate(
screen: 'edit'
)
if errors if errors
@log 'error', 'update', errors @log 'error', 'update', errors
@log 'error', errors
@formValidate(
form: e.target
errors: errors
screen: 'edit'
)
@formEnable(e) @formEnable(e)
@autosaveStart() @autosaveStart()
return return
# validate article # validate article
if params['body'] articleAttributes = App.TicketArticle.attributesGet( 'edit' )
if params['body'] || ( articleAttributes['body'] && articleAttributes['body']['null'] is false )
article = new App.TicketArticle article = new App.TicketArticle
params.from = @Session.get( 'firstname' ) + ' ' + @Session.get( 'lastname' ) params.from = @Session.get( 'firstname' ) + ' ' + @Session.get( 'lastname' )
params.ticket_id = ticket.id params.ticket_id = ticket.id
@ -534,6 +558,11 @@ class Edit extends App.Controller
errors = article.validate() errors = article.validate()
if errors if errors
@log 'error', 'update article', errors @log 'error', 'update article', errors
@formValidate(
form: e.target
errors: errors
screen: 'edit'
)
@formEnable(e) @formEnable(e)
@autosaveStart() @autosaveStart()
return return

View file

@ -109,13 +109,12 @@ class App.WidgetUser extends App.ControllerDrox
edit: (e) => edit: (e) =>
e.preventDefault() e.preventDefault()
new App.ControllerGenericEdit( new App.ControllerGenericEdit(
id: @user_id, id: @user_id
genericObject: 'User', genericObject: 'User'
required: 'quick', screen: 'edit'
pageData: { pageData:
title: 'Users', title: 'Users'
object: 'User', object: 'User'
objects: 'Users', objects: 'Users'
},
callback: @render callback: @render
) )

View file

@ -69,12 +69,26 @@ class App.Auth
App.Event.trigger( 'auth:logout' ) App.Event.trigger( 'auth:logout' )
App.Event.trigger( 'ui:rerender' ) App.Event.trigger( 'ui:rerender' )
# update model definition
if data.models
for model, attributes of data.models
for attribute in attributes
App[model].attributes.push attribute.name
App[model].configure_attributes.push attribute
return false; return false;
# clear local store # clear local store
if type isnt 'check' if type isnt 'check'
App.Event.trigger( 'clearStore' ) App.Event.trigger( 'clearStore' )
# update model definition
if data.models
for model, attributes of data.models
for attribute in attributes
App[model].attributes.push attribute.name
App[model].configure_attributes.push attribute
# update config # update config
for key, value of data.config for key, value of data.config
App.Config.set( key, value ) App.Config.set( key, value )
@ -129,4 +143,3 @@ class App.Auth
App.Event.trigger( 'auth:logout' ) App.Event.trigger( 'auth:logout' )
App.Event.trigger( 'ui:rerender' ) App.Event.trigger( 'ui:rerender' )
App.Event.trigger( 'clearStore' ) App.Event.trigger( 'clearStore' )

View file

@ -64,19 +64,17 @@ class App.Model extends Spine.Model
return '???' return '???'
@validate: ( data = {} ) -> @validate: ( data = {} ) ->
attributes = _.clone( data['model'].configure_attributes )
return if !attributes
# check params of screen if screen is requested # based on model attrbutes
if data['screen'] if App[ data['model'] ] && App[ data['model'] ].attributesGet
for attribute in attributes attributes = App[ data['model'] ].attributesGet( data['screen'] )
if attribute.screen
if attribute && attribute.screen && attribute.screen[ data['screen'] ] && !_.isEmpty(attribute.screen[ data['screen'] ]) # based on custom attributes
for item, value of attribute.screen[ data['screen'] ] else if data['model'].configure_attributes
attribute[item] = value attributes = App.Model.attributesGet( data['screen'], data['model'].configure_attributes )
# check required_if attributes # check required_if attributes
for attribute in attributes for attributeName, attribute of attributes
if attribute['required_if'] if attribute['required_if']
for key, values of attribute['required_if'] for key, values of attribute['required_if']
@ -98,7 +96,7 @@ class App.Model extends Spine.Model
# check attributes/each attribute of object # check attributes/each attribute of object
errors = {} errors = {}
for attribute in attributes for attributeName, attribute of attributes
# only if attribute is not read only # only if attribute is not read only
if !attribute.readonly if !attribute.readonly
@ -111,25 +109,25 @@ class App.Model extends Spine.Model
if parts[0] && !parts[1] if parts[0] && !parts[1]
# key exists not in hash || value is '' || value is undefined # key exists not in hash || value is '' || value is undefined
if !( attribute.name of data['params'] ) || data['params'][attribute.name] is '' || data['params'][attribute.name] is undefined if !( attributeName of data['params'] ) || data['params'][attributeName] is '' || data['params'][attributeName] is undefined
errors[attribute.name] = 'is required' errors[attributeName] = 'is required'
else if parts[0] && parts[1] && !parts[2] else if parts[0] && parts[1] && !parts[2]
# key exists not in hash || value is '' || value is undefined # key exists not in hash || value is '' || value is undefined
if !data.params[parts[0]] || !( parts[1] of data.params[parts[0]] ) || data.params[parts[0]][parts[1]] is '' || data.params[parts[0]][parts[1]] is undefined if !data.params[parts[0]] || !( parts[1] of data.params[parts[0]] ) || data.params[parts[0]][parts[1]] is '' || data.params[parts[0]][parts[1]] is undefined
errors[attribute.name] = 'is required' errors[attributeName] = 'is required'
else else
throw "can't parse '#{attribute.name}'" throw "can't parse '#{attribute.name}'"
# check confirm password # check confirm password
if attribute.type is 'password' && data['params'][attribute.name] && "#{attribute.name}_confirm" of data['params'] if attribute.type is 'password' && data['params'][attributeName] && "#{attributeName}_confirm" of data['params']
# get confirm password # get confirm password
if data['params'][attribute.name] isnt data['params']["#{attribute.name}_confirm"] if data['params'][attributeName] isnt data['params']["#{attributeName}_confirm"]
errors[attribute.name] = 'didn\'t match' errors[attributeName] = 'didn\'t match'
errors["#{attribute.name}_confirm"] = '' errors["#{attributeName}_confirm"] = ''
# return error object # return error object
if !_.isEmpty(errors) if !_.isEmpty(errors)
@ -139,9 +137,41 @@ class App.Model extends Spine.Model
# return no errors # return no errors
return return
###
attributes = App.Model.attributesGet(optionalScreen, optionalAttributesList)
###
@attributesGet: (screen = undefined, attributes = false) ->
if !attributes
attributes = clone( App[ @.className ].configure_attributes )
else
attributes = clone( attributes )
# in case if no configure_attributes exist
return if !attributes
attributesNew = {}
# check params of screen if screen is requested
if screen
for attribute in attributes
if attribute.screen
if attribute && attribute.screen && attribute.screen[ screen ] && !_.isEmpty( attribute.screen[ screen ] )
for item, value of attribute.screen[ screen ]
attribute[item] = value
attributesNew[ attribute.name ] = attribute
if !screen || _.isEmpty( attributesNew )
console.log(attributesNew)
for attribute in attributes
attributesNew[ attribute.name ] = attribute
attributesNew
validate: (params = {}) -> validate: (params = {}) ->
App.Model.validate( App.Model.validate(
model: @constructor model: @constructor.className
params: @ params: @
screen: params.screen screen: params.screen
) )

View file

@ -6,20 +6,20 @@ class App.User extends App.Model
# @hasMany 'roles', 'App.Role' # @hasMany 'roles', 'App.Role'
@configure_attributes = [ @configure_attributes = [
{ name: 'login', display: 'Login', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', autocapitalize: false, signup: false, quick: false }, { 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, quick: true, info: true, invite_agent: true }, { 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, quick: 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, quick: 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, quick: true, info: 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: true, 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, quick: false, }, { 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', quick: true, info: 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: '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: '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: 'active', display: 'Active', tag: 'boolean', default: true, null: true, class: 'span4' },

View file

@ -14,8 +14,8 @@
</div> </div>
<form class="form-horizontal form-large ticket-create"> <form class="form-horizontal form-large ticket-create">
<input type="hidden" value="" name="article_type"/> <div class="ticket-form"></div>
<div class="span9 ticket_create"></div> <div class="article-form"></div>
<div class="form-actions"> <div class="form-actions">
<button type="reset" class="btn cancel"><%- @T( 'Cancel' ) %></button>&nbsp;<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button> <button type="reset" class="btn cancel"><%- @T( 'Cancel' ) %></button>&nbsp;<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button>
</div> </div>

View file

@ -11,8 +11,8 @@
</div> </div>
<div class="page-content"> <div class="page-content">
<form class="form-horizontal form-large"> <form class="form-horizontal form-large">
<input type="hidden" value="" name="article_type"/> <div class="ticket-form"></div>
<div id="form_create"></div> <div class="article-form"></div>
<div class="form-actions"> <div class="form-actions">
<button type="reset" class="btn btn-default cancel"><%- @T( 'Cancel' ) %></button> <button type="reset" class="btn btn-default cancel"><%- @T( 'Cancel' ) %></button>
<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button> <button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button>

View file

@ -1,5 +1,5 @@
<div class="form-group <%= @attribute.item_class %>"> <div class="form-group <%= @attribute.item_class %>">
<label for="<%= @attribute.id %>"><%- @T( @attribute.display ) %><% if !@attribute.null: %> *<% end %></label> <label for="<%= @attribute.id %>"><%- @T( @attribute.display ) %> <span><% if !@attribute.null: %>*<% end %></span></label>
<div class="controls"> <div class="controls">
<%- @item %><% if @attribute.note: %><span class="glyphicon glyphicon-question-sign help-message" title="<%- @Ti( @attribute.note ) + ' ' %>"></span><% end %> <%- @item %><% if @attribute.note: %><span class="glyphicon glyphicon-question-sign help-message" title="<%- @Ti( @attribute.note ) + ' ' %>"></span><% end %>
<% if @attribute.remove: %><span><a href="#" class="glyphicon glyphicon-minus"></a></span><% end %> <% if @attribute.remove: %><span><a href="#" class="glyphicon glyphicon-minus"></a></span><% end %>

View file

@ -0,0 +1 @@
<input id="<%= @attribute.id %>" type="<%= @attribute.type %>" class="form-control <%= @attribute.class %>" placeholder="<%= @attribute.placeholder %>" name="<%= @attribute.name %>" value="<%= @attribute.value %>" <%= @attribute.required %>>

View file

@ -33,8 +33,12 @@ class SessionsController < ApplicationController
# auto population of default collections # auto population of default collections
collections, assets = SessionHelper::default_collections(user) collections, assets = SessionHelper::default_collections(user)
# add session user assets
assets = user.assets(assets) assets = user.assets(assets)
# get models
models = SessionHelper::models(user)
# check logon session # check logon session
logon_session_key = nil logon_session_key = nil
if params['logon_session'] if params['logon_session']
@ -50,6 +54,7 @@ class SessionsController < ApplicationController
# return new session data # return new session data
render :json => { render :json => {
:session => user, :session => user,
:models => models,
:collections => collections, :collections => collections,
:assets => assets, :assets => assets,
:logon_session => logon_session_key, :logon_session => logon_session_key,
@ -75,9 +80,13 @@ class SessionsController < ApplicationController
end end
if !user_id if !user_id
# get models
models = SessionHelper::models()
render :json => { render :json => {
:error => 'no valid session', :error => 'no valid session',
:config => config_frontend, :config => config_frontend,
:models => models,
} }
return return
end end
@ -89,13 +98,18 @@ class SessionsController < ApplicationController
# auto population of default collections # auto population of default collections
collections, assets = SessionHelper::default_collections(user) collections, assets = SessionHelper::default_collections(user)
# add session user assets
assets = user.assets(assets) assets = user.assets(assets)
# get models
models = SessionHelper::models(user)
# return current session # return current session
render :json => { render :json => {
:session => user, :session => user,
:models => models,
:collections => collections, :collections => collections,
:assets => assets, :assets => assets,
:config => config_frontend, :config => config_frontend,
} }
end end

View file

@ -255,24 +255,12 @@ class TicketsController < ApplicationController
) )
end end
# get related users
assets = {}
assets = ticket.assets(assets)
# get attributes to update # get attributes to update
attributes_to_change = Ticket::ScreenOptions.attributes_to_change( :user => current_user, :ticket => ticket ) attributes_to_change = Ticket::ScreenOptions.attributes_to_change( :user => current_user, :ticket => ticket )
attributes_to_change[:owner_id].each { |user_id| # get related users
user = User.find(user_id) assets = attributes_to_change[:assets]
assets = user.assets(assets) assets = ticket.assets(assets)
}
attributes_to_change[:group_id__owner_id].each {|group_id, user_ids|
user_ids.each {|user_id|
user = User.find(user_id)
assets = user.assets(assets)
}
}
# get related articles # get related articles
articles = Ticket::Article.where( :ticket_id => params[:id] ) articles = Ticket::Article.where( :ticket_id => params[:id] )
@ -297,6 +285,7 @@ class TicketsController < ApplicationController
:ticket_article_ids => article_ids, :ticket_article_ids => article_ids,
:signature => signature, :signature => signature,
:assets => assets, :assets => assets,
:form_meta => attributes_to_change,
:edit_form => attributes_to_change, :edit_form => attributes_to_change,
} }
end end
@ -311,20 +300,7 @@ class TicketsController < ApplicationController
# :article_id => params[:article_id] # :article_id => params[:article_id]
) )
assets = {} assets = attributes_to_change[:assets]
assets[ User.to_app_model ] = {}
attributes_to_change[:owner_id].each { |user_id|
user = User.find(user_id)
assets = user.assets(assets)
}
attributes_to_change[:group_id__owner_id].each {|group_id, user_ids|
user_ids.each {|user_id|
user = User.find(user_id)
assets = user.assets(assets)
}
}
# split data # split data
split = {} split = {}
if params[:ticket_id] && params[:article_id] if params[:ticket_id] && params[:article_id]
@ -332,12 +308,6 @@ class TicketsController < ApplicationController
split[:ticket_id] = ticket.id split[:ticket_id] = ticket.id
assets = ticket.assets(assets) assets = ticket.assets(assets)
owner_ids = []
ticket.agent_of_group.each { |user|
owner_ids.push user.id
assets = user.assets(assets)
}
# get related articles # get related articles
article = Ticket::Article.find( params[:article_id] ) article = Ticket::Article.find( params[:article_id] )
split[:article_id] = article.id split[:article_id] = article.id
@ -348,7 +318,7 @@ class TicketsController < ApplicationController
render :json => { render :json => {
:split => split, :split => split,
:assets => assets, :assets => assets,
:edit_form => attributes_to_change, :form_meta => attributes_to_change,
} }
end end

View file

@ -0,0 +1,147 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class ObjectManager
=begin
add a new activity entry for an object
ObjectManager.listObjects()
=end
def self.listObjects
['Ticket', 'TicketArticle', 'Group', 'Organization', 'User']
end
end
class ObjectManager::Attribute < ApplicationModel
self.table_name = 'object_manager_attributes'
belongs_to :object_lookup, :class_name => 'ObjectLookup'
validates :name, :presence => true
store :screens
store :data_option
=begin
add a new activity entry for an object
ObjectManager::Attribute.add(
:object => 'Ticket',
:name => 'group_id',
:frontend => 'Group',
:data_type => 'select',
:data_option => {
:relation => 'Group',
:relation_condition => { :access => 'rw' },
:multiple => false,
:null => true,
},
:editable => false,
:active => true,
:screens => {
:create => {
'-all-' => {
:required => true,
},
},
:edit => {
:Agent => {
:required => true,
},
},
},
:pending_migration => false,
:position => 20,
:created_by_id => 1,
:updated_by_id => 1,
:created_at => '2014-06-04 10:00:00',
:updated_at => '2014-06-04 10:00:00',
)
=end
def self.add(data)
# lookups
if data[:object]
data[:object_lookup_id] = ObjectLookup.by_name( data[:object] )
end
data.delete(:object)
# check newest entry - is needed
result = ObjectManager::Attribute.where(
:object_lookup_id => data[:object_lookup_id],
:name => data[:name],
).first
if result
# raise "ERROR: attribute #{data[:name]} for #{data[:object]} already exists"
return result.update_attributes(data)
end
# create history
ObjectManager::Attribute.create(data)
end
=begin
get list of object attributes
attribute_list = ObjectManager::Attribute.by_object('Ticket', user)
returns:
[
{ :name => 'api_key', :display => 'API KEY', :tag => 'input', :null => true, :edit => true, :maxlength => 32 },
{ :name => 'api_ip_regexp', :display => 'API IP RegExp', :tag => 'input', :null => true, :edit => true },
{ :name => 'api_ip_max', :display => 'API IP Max', :tag => 'input', :null => true, :edit => true },
]
=end
def self.by_object(object, user)
# lookups
if object
object_lookup_id = ObjectLookup.by_name( object )
end
# get attributes in right order
result = ObjectManager::Attribute.where(
:object_lookup_id => object_lookup_id,
:active => true,
).order('position ASC')
attributes = []
result.each {|item|
data = {
:name => item.name,
:display => item.display,
:tag => item.data_type,
#:null => item.null,
}
if item.screens
data[:screen] = {}
item.screens.each {|screen, roles_options |
data[:screen][screen] = {}
roles_options.each {|role, options|
if role == '-all-'
data[:screen][screen] = options
elsif user && user.is_role(role)
data[:screen][screen] = options
end
}
}
end
if item.data_option
data = data.merge( item.data_option )
end
attributes.push data
}
attributes
end
end

View file

@ -56,6 +56,8 @@ class Ticket < ApplicationModel
belongs_to :create_article_type, :class_name => 'Ticket::Article::Type' belongs_to :create_article_type, :class_name => 'Ticket::Article::Type'
belongs_to :create_article_sender, :class_name => 'Ticket::Article::Sender' belongs_to :create_article_sender, :class_name => 'Ticket::Article::Sender'
self.inheritance_column = nil
attr_accessor :callback_loop attr_accessor :callback_loop
=begin =begin

View file

@ -50,6 +50,9 @@ returns
params[:article] = self.find( params[:article_id] ) params[:article] = self.find( params[:article_id] )
end end
filter = {}
assets = {}
# get ticket states # get ticket states
state_ids = [] state_ids = []
if params[:ticket] if params[:ticket]
@ -63,44 +66,21 @@ returns
state_type = Ticket::StateType.where( :name => type ).first state_type = Ticket::StateType.where( :name => type ).first
if state_type if state_type
state_type.states.each {|state| state_type.states.each {|state|
assets = state.assets(assets)
state_ids.push state.id state_ids.push state.id
} }
end end
} }
filter[:state_id] = state_ids
# get owner
owner_ids = []
if params[:ticket]
params[:ticket].agent_of_group.each { |user|
owner_ids.push user.id
}
end
# get group
group_ids = []
Group.where( :active => true ).each { |group|
group_ids.push group.id
}
# get group / user relations
agents = {}
Ticket::ScreenOptions.agents.each { |user|
agents[ user.id ] = 1
}
groups_users = {}
group_ids.each {|group_id|
groups_users[ group_id ] = []
Group.find( group_id ).users.each {|user|
next if !agents[ user.id ]
groups_users[ group_id ].push user.id
}
}
# get priorities # get priorities
priority_ids = [] priority_ids = []
Ticket::Priority.where( :active => true ).each { |priority| Ticket::Priority.where( :active => true ).each { |priority|
assets = priority.assets(assets)
priority_ids.push priority.id priority_ids.push priority.id
} }
filter[:priority_id] = priority_ids
type_ids = [] type_ids = []
if params[:ticket] if params[:ticket]
@ -115,14 +95,29 @@ returns
end end
} }
end end
filter[:type_id] = type_ids
# get group / user relations
agents = {}
Ticket::ScreenOptions.agents.each { |user|
agents[ user.id ] = 1
}
dependencies = { :group_id => { '' => [] } }
Group.where( :active => true ).each { |group|
assets = group.assets(assets)
dependencies[:group_id][group.id] = { :owner_id => [] }
group.users.each {|user|
next if !agents[ user.id ]
assets = user.assets(assets)
dependencies[:group_id][ group.id ][ :owner_id ].push user.id
}
}
return { return {
:type_id => type_ids, :assets => assets,
:state_id => state_ids, :filter => filter,
:priority_id => priority_ids, :dependencies => dependencies,
:owner_id => owner_ids,
:group_id => group_ids,
:group_id__owner_id => groups_users,
} }
end end
@ -131,8 +126,8 @@ returns
list tickets by customer groupd in state categroie open and closed list tickets by customer groupd in state categroie open and closed
result = Ticket::ScreenOptions.list_by_customer( result = Ticket::ScreenOptions.list_by_customer(
:customer_id => 123, :customer_id => 123,
:limit => 15, # optional, default 15 :limit => 15, # optional, default 15
) )
returns returns
@ -152,13 +147,13 @@ returns
# get tickets # get tickets
tickets_open = Ticket.where( tickets_open = Ticket.where(
:customer_id => data[:customer_id], :customer_id => data[:customer_id],
:state_id => state_list_open :state_id => state_list_open
).limit( data[:limit] || 15 ).order('created_at DESC') ).limit( data[:limit] || 15 ).order('created_at DESC')
tickets_closed = Ticket.where( tickets_closed = Ticket.where(
:customer_id => data[:customer_id], :customer_id => data[:customer_id],
:state_id => state_list_closed :state_id => state_list_closed
).limit( data[:limit] || 15 ).order('created_at DESC') ).limit( data[:limit] || 15 ).order('created_at DESC')
return { return {

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,16 @@ module SessionHelper
return default_collection, assets return default_collection, assets
end end
def self.models(user = nil)
models = {}
objects = ObjectManager.listObjects
objects.each {|object|
attributes = ObjectManager::Attribute.by_object(object, user)
models[object] = attributes
}
models
end
def self.cleanup_expired def self.cleanup_expired
# web sessions # web sessions

View file

@ -495,3 +495,54 @@ test( "form selector", function() {
deepEqual( params, test_params, 'form param check via $("#form").parent()' ); deepEqual( params, test_params, 'form param check via $("#form").parent()' );
}); });
test( "form required_if + shown_if", function() {
$('#forms').append('<hr><h1>form required_if + shown_if</h1><div><form id="form7"></form></div>')
var el = $('#form7')
var defaults = {
input2: 'some name66',
}
new App.ControllerForm({
el: el,
model: {
configure_attributes: [
{ name: 'input1', display: 'Input1', tag: 'input', type: 'text', limit: 100, null: true, default: 'some not used default33' },
{ name: 'input2', display: 'Input2', tag: 'input', type: 'text', limit: 100, null: true, default: 'some used default', required_if: { active: true }, shown_if: { active: true } },
{ name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, null: false },
],
},
params: defaults,
});
test_params = {
input1: "some not used default33",
input2: "some name66",
active: true
};
params = App.ControllerForm.params( el )
deepEqual( params, test_params, 'form param check via $("#form")' );
equal( el.find('[name="input2"]').attr('required'), 'required', 'check required attribute of input2 ')
equal( el.find('[name="input2"]').is(":visible"), true, 'check visible attribute of input2 ')
el.find('[name="active"]').val('{boolean}::false').trigger('change')
test_params = {
input1: "some not used default33",
active: false
};
params = App.ControllerForm.params( el )
deepEqual( params, test_params, 'form param check via $("#form")' );
equal( el.find('[name="input2"]').attr('required'), undefined, 'check required attribute of input2 ')
equal( el.find('[name="input2"]').is(":visible"), false, 'check visible attribute of input2 ')
el.find('[name="active"]').val('{boolean}::true').trigger('change')
test_params = {
input1: "some not used default33",
input2: "some name66",
active: true
};
params = App.ControllerForm.params( el )
deepEqual( params, test_params, 'form param check via $("#form")' );
equal( el.find('[name="input2"]').attr('required'), 'required', 'check required attribute of input2 ')
equal( el.find('[name="input2"]').is(":visible"), true, 'check visible attribute of input2 ')
});

View file

@ -0,0 +1,200 @@
// model
test( "model basic tests", function() {
// define model
var configure_attributes_org = _.clone( App.Ticket.configure_attributes )
var attribute1 = {
name: 'test1', display: 'Test 1', tag: 'input', type: 'text', limit: 200, 'null': false
};
App.Ticket.configure_attributes.push( attribute1 )
var attribute2 = {
name: 'test2', display: 'Test 2', tag: 'input', type: 'text', limit: 200, 'null': true
};
App.Ticket.configure_attributes.push( attribute2 )
var attribute3 = {
name: 'pending_time1', display: 'Pending till1', tag: 'input', type: 'text', limit: 200, 'null': false, required_if: { state_id: [3] },
};
App.Ticket.configure_attributes.push( attribute3 )
var attribute4 = {
name: 'pending_time2', display: 'Pending till2', tag: 'input', type: 'text', limit: 200, 'null': true, required_if: { state_id: [3] },
};
App.Ticket.configure_attributes.push( attribute4 )
// check validation
console.log('TEST 1')
var ticket = new App.Ticket()
ticket.load({title: 'some title'})
var error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
ok( !error['pending_time1'], 'pending_time1 is not required')
ok( !error['pending_time2'], 'pending_time2 is not required')
console.log('TEST 2')
ticket.title = 'some new title'
ticket.state_id = [2,3]
ticket.test2 = 123
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title exists')
ok( !error['state_id'], 'state_id is')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
ok( error['pending_time1'], 'pending_time1 is required')
ok( error['pending_time2'], 'pending_time2 is required')
console.log('TEST 3')
ticket.title = 'some new title'
ticket.state_id = [2,1]
ticket.test2 = 123
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title exists')
ok( !error['state_id'], 'state_id is')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
ok( !error['pending_time1'], 'pending_time1 is required')
ok( !error['pending_time2'], 'pending_time2 is required')
console.log('TEST 4')
ticket.title = 'some new title'
ticket.state_id = [2,3]
ticket.test2 = 123
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title exists')
ok( !error['state_id'], 'state_id is')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
ok( error['pending_time1'], 'pending_time1 is required')
ok( error['pending_time2'], 'pending_time2 is required')
console.log('TEST 5')
ticket.title = 'some new title'
ticket.state_id = [2,3]
ticket.test2 = 123
ticket.pending_time1 = '2014-10-10 09:00'
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title exists')
ok( !error['state_id'], 'state_id is')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
ok( !error['pending_time1'], 'pending_time1 is required')
ok( error['pending_time2'], 'pending_time2 is required')
// define model with screen
App.Ticket.configure_attributes = configure_attributes_org
var attribute1 = {
name: 'test1', display: 'Test 1', tag: 'input', type: 'text', limit: 200, 'null': false, screen: { some_screen: { required_if: { state_id: [3] } } },
};
App.Ticket.configure_attributes.push( attribute1 )
var attribute2 = {
name: 'test2', display: 'Test 2', tag: 'input', type: 'text', limit: 200, 'null': true, screen: { some_screen: { required_if: { state_id: [3] } } },
};
App.Ticket.configure_attributes.push( attribute2 )
var attribute3 = {
name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, relation: 'Group', screen: { some_screen: { null: false } },
};
App.Ticket.configure_attributes.push( attribute3 )
var attribute4 = {
name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: false, relation: 'User', screen: { some_screen: { null: false } },
};
App.Ticket.configure_attributes.push( attribute4 )
var attribute5 = {
name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, relation: 'TicketState', screen: { some_screen: { null: false } },
};
App.Ticket.configure_attributes.push( attribute5 )
// check validation with screen
console.log('TEST 6')
ticket = new App.Ticket()
ticket.load({title: 'some title'})
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
console.log('TEST 7')
ticket.state_id = 3
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
console.log('TEST 8')
ticket.state_id = 2
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
console.log('TEST 9')
ticket.state_id = undefined
error = ticket.validate({screen: 'some_screen'})
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( error['state_id'], 'state_id is required')
ok( !error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is required')
console.log('TEST 10')
ticket.state_id = 2
error = ticket.validate({screen: 'some_screen'})
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( !error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
console.log('TEST 11')
ticket.state_id = 3
error = ticket.validate({screen: 'some_screen'})
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( error['test2'], 'test2 is required')
console.log('TEST 12')
ticket.state_id = 2
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
console.log('TEST 13')
ticket.state_id = 3
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is required')
console.log('TEST 14')
ticket.state_id = 2
error = ticket.validate()
ok( error['group_id'], 'group_id is required')
ok( !error['title'], 'title is required')
ok( !error['state_id'], 'state_id is required')
ok( error['test1'], 'test1 is required')
ok( !error['test2'], 'test2 is not required')
});

View file

@ -111,8 +111,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => true, :match_result => true,
}, },
{ {
@ -127,8 +128,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
@ -150,8 +152,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance1, :where => :instance1,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => true, :match_result => true,
}, },
@ -204,8 +207,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance1, :where => :instance1,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
{ {
@ -219,8 +223,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
@ -246,8 +251,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance1, :where => :instance1,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
{ {
@ -261,8 +267,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
@ -280,8 +287,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => true, :match_result => true,
}, },
{ {
@ -298,8 +306,9 @@ class AgentTicketActionsLevel3Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active .reset-message',
:value => 'Discard your unsaved changes.', :value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => true, :match_result => true,
}, },
{ {
@ -315,7 +324,9 @@ class AgentTicketActionsLevel3Test < TestCase
:where => :instance2, :where => :instance2,
:execute => 'match', :execute => 'match',
:css => '.content_permanent.active', :css => '.content_permanent.active',
:value => 'Discard your unsaved changes.', :css => '.content_permanent.active .reset-message',
:value => '(Discard your unsaved changes.|Verwerfen der)',
:no_quote => true,
:match_result => false, :match_result => false,
}, },
{ {

View file

@ -3,8 +3,8 @@ require 'browser_test_helper'
class AgentTicketActionLevel5Test < TestCase class AgentTicketActionLevel5Test < TestCase
def test_I def test_I
random = 'text_module_test_' + rand(999999).to_s random = 'text_module_test_' + rand(99999999).to_s
random2 = 'text_module_test_' + rand(999999).to_s random2 = 'text_module_test_' + rand(99999999).to_s
# user # user
tests = [ tests = [
@ -153,9 +153,9 @@ class AgentTicketActionLevel5Test < TestCase
browser_signle_test_with_login(tests, { :username => 'master@example.com' }) browser_signle_test_with_login(tests, { :username => 'master@example.com' })
end end
def test_II def test_II
random = 'text_II_module_test_' + rand(999999).to_s random = 'text_II_module_test_' + rand(99999999).to_s
user_rand = rand(999999).to_s user_rand = rand(99999999).to_s
login = 'agent-text-module-' + user_rand login = 'agent-text-module-' + user_rand
firstname = 'Text' + user_rand firstname = 'Text' + user_rand
lastname = 'Module' + user_rand lastname = 'Module' + user_rand
@ -191,7 +191,7 @@ class AgentTicketActionLevel5Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'set', :execute => 'set',
:css => '.active input[name=subject]', :css => '.active input[name=title]',
:value => 'A', :value => 'A',
}, },
{ {
@ -207,7 +207,7 @@ class AgentTicketActionLevel5Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'set', :execute => 'set',
:css => '.active input[name=subject]', :css => '.active input[name=title]',
:value => 'B', :value => 'B',
}, },
@ -330,7 +330,7 @@ class AgentTicketActionLevel5Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => 'nicole', :value => 'nicole',
}, },
{ {
@ -340,13 +340,13 @@ class AgentTicketActionLevel5Test < TestCase
{ {
:where => :instance2, :where => :instance2,
:execute => 'sendkey', :execute => 'sendkey',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => :arrow_down, :value => :arrow_down,
}, },
{ {
:where => :instance2, :where => :instance2,
:execute => 'sendkey', :execute => 'sendkey',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => :tab, :value => :tab,
}, },
{ {
@ -425,7 +425,7 @@ class AgentTicketActionLevel5Test < TestCase
}, },
{ {
:execute => 'wait', :execute => 'wait',
:value => 4, :value => 2,
}, },
{ {
:where => :instance2, :where => :instance2,
@ -536,7 +536,7 @@ class AgentTicketActionLevel5Test < TestCase
}, },
{ {
:execute => 'wait', :execute => 'wait',
:value => 0.2, :value => 0.5,
}, },
# { # {
# :where => :instance2, # :where => :instance2,

View file

@ -142,7 +142,7 @@ class AgentUserManageTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => customer_user_email, :value => customer_user_email,
}, },
{ {
@ -151,12 +151,12 @@ class AgentUserManageTest < TestCase
}, },
{ {
:execute => 'sendkey', :execute => 'sendkey',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => :arrow_down, :value => :arrow_down,
}, },
{ {
:execute => 'sendkey', :execute => 'sendkey',
:css => '.active .ticket_create input[name="customer_id_autocompletion"]', :css => '.active .ticket-create input[name="customer_id_autocompletion"]',
:value => :tab, :value => :tab,
}, },
{ {

View file

@ -27,7 +27,7 @@ class CustomerTicketCreateTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.ticket-create input[name="subject"]', :css => '.ticket-create input[name="title"]',
:value => 'some subject 123äöü', :value => 'some subject 123äöü',
}, },
{ {

View file

@ -32,12 +32,12 @@ class TaskbarTaskTest < TestCase
}, },
{ {
:execute => 'check', :execute => 'check',
:css => '.active .ticket_create', :css => '.active .ticket-create',
:result => true, :result => true,
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create input[name="subject"]', :css => '.active .ticket-create input[name="title"]',
:value => 'some test AAA', :value => 'some test AAA',
}, },
{ {
@ -113,7 +113,7 @@ class TaskbarTaskTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create input[name="subject"]', :css => '.active .ticket-create input[name="title"]',
:value => 'INBOUND TEST#1', :value => 'INBOUND TEST#1',
}, },
{ {
@ -122,7 +122,7 @@ class TaskbarTaskTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create textarea[name="body"]', :css => '.active .ticket-create textarea[name="body"]',
:value => 'INBOUND BODY TEST#1', :value => 'INBOUND BODY TEST#1',
}, },
{ {
@ -139,7 +139,7 @@ class TaskbarTaskTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create input[name="subject"]', :css => '.active .ticket-create input[name="title"]',
:value => 'OUTBOUND TEST#1', :value => 'OUTBOUND TEST#1',
}, },
{ {
@ -148,7 +148,7 @@ class TaskbarTaskTest < TestCase
}, },
{ {
:execute => 'set', :execute => 'set',
:css => '.active .ticket_create textarea[name="body"]', :css => '.active .ticket-create textarea[name="body"]',
:value => 'OUTBOUND BODY TEST#1', :value => 'OUTBOUND BODY TEST#1',
}, },
{ {

View file

@ -297,40 +297,40 @@ class TestCase < Test::Unit::TestCase
elsif action[:execute] == 'create_ticket' elsif action[:execute] == 'create_ticket'
instance.find_element( { :css => 'a[href="#new"]' } ).click instance.find_element( { :css => 'a[href="#new"]' } ).click
instance.find_element( { :css => 'a[href="#ticket/create/call_inbound"]' } ).click instance.find_element( { :css => 'a[href="#ticket/create/call_inbound"]' } ).click
element = instance.find_element( { :css => '.active .ticket_create' } ) element = instance.find_element( { :css => '.active .ticket-create' } )
if !element if !element
assert( false, "(#{test[:name]}) no ticket create screen found!" ) assert( false, "(#{test[:name]}) no ticket create screen found!" )
return return
end end
sleep 2 sleep 2
element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } ) element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
element.clear element.clear
element.send_keys( 'nico*' ) element.send_keys( 'nico*' )
sleep 4 sleep 4
element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } ) element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
element.send_keys( :arrow_down ) element.send_keys( :arrow_down )
sleep 0.2 sleep 0.2
element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } ) element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
element.send_keys( :tab ) element.send_keys( :tab )
sleep 0.1 sleep 0.1
element = instance.find_element( { :css => '.active .ticket_create select[name="group_id"]' } ) element = instance.find_element( { :css => '.active .ticket-create select[name="group_id"]' } )
dropdown = Selenium::WebDriver::Support::Select.new(element) dropdown = Selenium::WebDriver::Support::Select.new(element)
dropdown.select_by( :text, action[:group]) dropdown.select_by( :text, action[:group])
sleep 0.1 sleep 0.1
element = instance.find_element( { :css => '.active .ticket_create input[name="subject"]' } ) element = instance.find_element( { :css => '.active .ticket-create input[name="title"]' } )
element.clear element.clear
element.send_keys( action[:subject] ) element.send_keys( action[:subject] )
sleep 0.1 sleep 0.1
element = instance.find_element( { :css => '.active .ticket_create textarea[name="body"]' } ) element = instance.find_element( { :css => '.active .ticket-create textarea[name="body"]' } )
element.clear element.clear
element.send_keys( action[:body] ) element.send_keys( action[:body] )
if action[:do_not_submit] if action[:do_not_submit]
assert( true, "(#{test[:name]}) ticket created without submit" ) assert( true, "(#{test[:name]}) ticket created without submit" )
return return
end end
sleep 0.5 sleep 0.8
instance.find_element( { :css => '.active .form-actions button[type="submit"]' } ).click instance.find_element( { :css => '.active .form-actions button[type="submit"]' } ).click
sleep 2 sleep 1
(1..14).each {|loop| (1..14).each {|loop|
if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/ if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
assert( true, "(#{test[:name]}) ticket created" ) assert( true, "(#{test[:name]}) ticket created" )
@ -338,7 +338,7 @@ class TestCase < Test::Unit::TestCase
end end
sleep 0.5 sleep 0.5
} }
assert( true, "(#{test[:name]}) ticket creation failed, can't get zoom url" ) assert( false, "(#{test[:name]}) ticket creation failed, can't get zoom url" )
return return
elsif action[:execute] == 'close_all_tasks' elsif action[:execute] == 'close_all_tasks'
for i in 1..100 for i in 1..100