Split of _application_controller_form.js.coffee into single files for each ui element.

This commit is contained in:
Martin Edenhofer 2015-09-13 19:59:15 +02:00
parent 79666ba324
commit 971321b369
20 changed files with 1206 additions and 1150 deletions

View file

@ -0,0 +1,221 @@
class App.UiElement.ApplicationUiElement
# sort attribute.options
@sortOptions: (attribute) ->
# skip sorting if it is disabled by config
return if attribute.sortBy == null
return if !attribute.options
if _.isArray( attribute.options )
# reverse if we have to exit early, if configured
if attribute.order
if attribute.order == 'DESC'
attribute.options = attribute.options.reverse()
return
options_by_name = []
for i in attribute.options
options_by_name.push i['name'].toString().toLowerCase()
options_by_name = options_by_name.sort()
options_new = []
options_new_used = {}
for i in options_by_name
for ii, vv in attribute.options
if !options_new_used[ ii['value'] ] && i.toString().toLowerCase() is ii['name'].toString().toLowerCase()
options_new_used[ ii['value'] ] = 1
options_new.push ii
attribute.options = options_new
# do a final reverse, if configured
if attribute.order
if attribute.order == 'DESC'
attribute.options = attribute.options.reverse()
@addNullOption: (attribute) ->
return if !attribute.options
return if !attribute.nulloption
if _.isArray( attribute.options )
attribute.options.unshift( { name: '-', value: '' } )
else
attribute.options[''] = '-'
@getConfigOptionList: (attribute) ->
return if !attribute.options
selection = attribute.options
attribute.options = []
if _.isArray( selection )
for row in selection
if attribute.translate
row.name = App.i18n.translateInline( row.name )
attribute.options.push row
else
order = _.sortBy(
_.keys(selection), (item) ->
selection[item].toString().toLowerCase()
)
for key in order
name_new = selection[key]
if attribute.translate
name_new = App.i18n.translateInline( name_new )
attribute.options.push {
name: name_new
value: key
}
@getRelationOptionList: (attribute, params) ->
# build options list based on relation
return if !attribute.relation
return if !App[attribute.relation]
attribute.options = []
list = []
if attribute.filter
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter', attribute.filter
# function based filter
if typeof attribute.filter is 'function'
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-function'
all = App[ attribute.relation ].search( sortBy: attribute.sortBy )
list = attribute.filter( all, 'collection', params )
# data based filter
else if attribute.filter[ attribute.name ]
filter = attribute.filter[ attribute.name ]
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-data', filter
# check all records
for record in App[ attribute.relation ].search( sortBy: attribute.sortBy )
# check all filter attributes
for key in filter
# check all filter values as array
# if it's matching, use it for selection
if record['id'] is key
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 || ( record['id'] && key && record['id'].toString() is key.toString() )
list.push record
# check if current value need to be added
if params[ attribute.name ]
hit = false
for value in list
if value['id'].toString() is params[ attribute.name ].toString()
hit = true
if !hit
currentRecord = App[ attribute.relation ].find( params[ attribute.name ] )
list.push currentRecord
# no data filter matched
else
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-data no filter matched'
list = App[ attribute.relation ].search( sortBy: attribute.sortBy )
else
App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-no filter defined'
list = App[ attribute.relation ].search( sortBy: attribute.sortBy )
App.Log.debug 'ControllerForm', '_getRelationOptionList', attribute, list
# build options list
@buildOptionList( list, attribute )
# build options list
@buildOptionList: (list, attribute) ->
for item in list
# if active or if active doesn't exist
if item.active || !( 'active' of item )
name_new = '?'
if item.displayName
name_new = item.displayName()
else if item.name
name_new = item.name
if attribute.translate
name_new = App.i18n.translateInline(name_new)
attribute.options.push {
name: name_new,
value: item.id,
note: item.note,
}
# execute filter
@filterOption: (attribute) ->
return if !attribute.filter
return if !attribute.options
return if typeof attribute.filter isnt 'function'
App.Log.debug 'ControllerForm', '_filterOption:filter-function'
attribute.options = attribute.filter( attribute.options, attribute )
# set selected attributes
@selectedOptions: (attribute) ->
return if !attribute.options
# check if selected / checked need to be set
check = (value, record) ->
if typeof value is 'string' || typeof value is 'number' || typeof value is 'boolean'
# if name or value is matching
if record.value.toString() is value.toString() || record.name.toString() is value.toString()
record.selected = 'selected'
record.checked = 'checked'
else if ( value && record.value && _.include( value, record.value ) ) || ( value && record.name && _.include( value, record.name ) )
record.selected = 'selected'
record.checked = 'checked'
# lookup of any record
for record in attribute.options
if _.isArray( attribute.value )
for value in attribute.value
check( value, record )
if typeof attribute.value is 'string' || typeof attribute.value is 'number' || typeof attribute.value is 'boolean'
check( attribute.value, record )
# if noting is selected / checked, use default as selected / checked
selected = false
for record in attribute.options
if record.selected || record.checked
selected = true
if !selected
for record in attribute.options
if typeof attribute.default is 'string' || typeof attribute.default is 'number' || typeof attribute.default is 'boolean'
check( attribute.default, record )
# set disabled attributes
@disabledOptions: (attribute) ->
return if !attribute.options
return if !_.isArray( attribute.options )
for record in attribute.options
if record.disable is true
record.disabled = 'disabled'
else
record.disabled = ''

View file

@ -0,0 +1,28 @@
class App.UiElement.active extends App.UiElement.ApplicationUiElement
@render: (attribute, params) ->
# set attributes
attribute.null = false
attribute.translation = true
# build options list
attribute.options = [
{ name: 'active', value: true }
{ name: 'inactive', value: false }
]
# set data type
if attribute.name
attribute.name = '{boolean}' + attribute.name
# build options list based on config
@getConfigOptionList( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
# return item
$( App.view('generic/select')( attribute: attribute ) )

View file

@ -0,0 +1,51 @@
class App.UiElement.autocompletion
@render: (attribute, params) ->
if params[ attribute.name + '_autocompletion_value_shown' ]
attribute.valueShown = params[ attribute.name + '_autocompletion_value_shown' ]
item = $( App.view('generic/autocompletion')( attribute: attribute ) )
a = =>
local_attribute = '#' + attribute.id
local_attribute_full = '#' + attribute.id + '_autocompletion'
@callback = attribute.callback
# call calback on init
if @callback && attribute.value && @params
@callback( @params )
b = (event, item) =>
# set html form attribute
$(local_attribute).val(item.id).trigger('change')
$(local_attribute + '_autocompletion_value_shown').val(item.value)
# call calback
if @callback
params = App.ControllerForm.params(form)
@callback( params )
###
$(@local_attribute_full).tagsInput(
autocomplete_url: '/users/search',
height: '30px',
width: '530px',
auto: {
source: '/users/search',
minLength: 2,
select: ( event, ui ) ->
#@log 'notice', 'selected', event, ui
b(event, ui.item)
}
)
###
source = attribute.source
if typeof(source) is 'string'
source = source.replace('#{@apiPath}', App.Config.get('api_path') );
$(local_attribute_full).autocomplete(
source: source,
minLength: attribute.minLengt || 3,
select: ( event, ui ) =>
b(event, ui.item)
)
App.Delay.set( a, 280, undefined, 'form_autocompletion' )
item

View file

@ -0,0 +1,25 @@
class App.UiElement.boolean extends App.UiElement.ApplicationUiElement
@render: (attribute, params) ->
# build options list
if _.isEmpty(attribute.options)
attribute.options = [
{ name: 'yes', value: true }
{ name: 'no', value: false }
]
# set data type
if attribute.name
attribute.name = '{boolean}' + attribute.name
# build options list based on config
@getConfigOptionList( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
# return item
$( App.view('generic/select')( attribute: attribute ) )

View file

@ -0,0 +1,25 @@
class App.UiElement.checkbox extends App.UiElement.ApplicationUiElement
@render: (attribute, params) ->
# build options list based on config
@getConfigOptionList( attribute, params )
# build options list based on relation
@getRelationOptionList( attribute, params )
# add null selection if needed
@addNullOption( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
# disable item of list
@disabledOptions( attribute, params )
# filter attributes
@filterOption( attribute, params )
$( App.view('generic/checkbox')( attribute: attribute ) )

View file

@ -0,0 +1,139 @@
class App.UiElement.date
@render: (attribute) ->
# set data type
if attribute.name
attribute.nameRaw = attribute.name
attribute.name = '{date}' + attribute.name
if attribute.value
if typeof( attribute.value ) is 'string'
unixtime = new Date( Date.parse( "#{attribute.value}T00:00:00Z" ) )
else
unixtime = new Date( attribute.value )
year = unixtime.getUTCFullYear()
month = unixtime.getUTCMonth() + 1
day = unixtime.getUTCDate()
hour = unixtime.getUTCHours()
minute = unixtime.getUTCMinutes()
item = $( App.view('generic/date')(
attribute: attribute
year: year
month: month
day: day
) )
setNewTime = (diff, el, reset) ->
name = $(el).closest('.form-group').find('[data-name]').attr('data-name')
# remove old validation
item.find('.has-error').removeClass('has-error')
item.closest('.form-group').find('.help-inline').html('')
day = item.closest('.form-group').find("[name=\"{date}#{name}___day\"]").val()
month = item.closest('.form-group').find("[name=\"{date}#{name}___month\"]").val()
year = item.closest('.form-group').find("[name=\"{date}#{name}___year\"]").val()
format = (number) ->
if parseInt(number) < 10
number = "0#{number}"
number
if !reset && (year isnt '' && month isnt '' && day isnt '')
time = new Date( Date.parse( "#{year}-#{format(month)}-#{format(day)}T00:00:00Z" ) )
time.setMinutes( time.getMinutes() + diff + time.getTimezoneOffset() )
else
time = new Date()
time.setMinutes( time.getMinutes() + diff )
item.closest('.form-group').find("[name=\"{date}#{name}___day\"]").val( time.getDate() )
item.closest('.form-group').find("[name=\"{date}#{name}___month\"]").val( time.getMonth()+1 )
item.closest('.form-group').find("[name=\"{date}#{name}___year\"]").val( time.getFullYear() )
item.find('.js-today').bind('click', (e) ->
e.preventDefault()
setNewTime(0, @, true)
)
item.find('.js-plus-day').bind('click', (e) ->
e.preventDefault()
setNewTime(60 * 24, @)
)
item.find('.js-minus-day').bind('click', (e) ->
e.preventDefault()
setNewTime(-60 * 24, @)
)
item.find('.js-plus-week').bind('click', (e) ->
e.preventDefault()
setNewTime(60 * 24 * 7, @)
)
item.find('.js-minus-week').bind('click', (e) ->
e.preventDefault()
setNewTime(-60 * 24 * 7, @)
)
item.find('input').bind('keyup blur focus change', (e) ->
# do validation
name = $(@).attr('name')
if name
fieldPrefix = name.split('___')[0]
# remove old validation
item.find('.has-error').removeClass('has-error')
item.closest('.form-group').find('.help-inline').html('')
day = item.closest('.form-group').find("[name=\"#{fieldPrefix}___day\"]").val()
month = item.closest('.form-group').find("[name=\"#{fieldPrefix}___month\"]").val()
year = item.closest('.form-group').find("[name=\"#{fieldPrefix}___year\"]").val()
# validate exists
errors = {}
if !day
errors.day = 'missing'
if !month
errors.month = 'missing'
if !year
errors.year = 'missing'
# ranges
if day
daysInMonth = 31
if month && year
daysInMonth = new Date(year, month, 0).getDate();
if parseInt(day).toString() is 'NaN'
errors.day = 'invalid'
else if parseInt(day) > daysInMonth || parseInt(day) < 1
errors.day = 'invalid'
if month
if parseInt(month).toString() is 'NaN'
errors.month = 'invalid'
else if parseInt(month) > 12 || parseInt(month) < 1
errors.month = 'invalid'
if year
if parseInt(year).toString() is 'NaN'
errors.year = 'invalid'
else if parseInt(year) > 2100 || parseInt(year) < 2001
errors.year = 'invalid'
if !_.isEmpty(errors)
# if field is required, if not do not show error
if year is '' && day is '' && month
if attribute.null
e.preventDefault()
e.stopPropagation()
return
else
item.closest('.form-group').find('.help-inline').text( 'is required' )
# show invalid options
for key, value of errors
item.closest('.form-group').addClass('has-error')
item.closest('.form-group').find("[name=\"#{fieldPrefix}___#{key}\"]").addClass('has-error')
#item.closest('.form-group').find('.help-inline').text( value )
e.preventDefault()
e.stopPropagation()
return
)
item

View file

@ -0,0 +1,172 @@
class App.UiElement.datetime
@render: (attribute) ->
# set data type
if attribute.name
attribute.nameRaw = attribute.name
attribute.name = '{datetime}' + attribute.name
if attribute.value
if typeof( attribute.value ) is 'string'
unixtime = new Date( Date.parse( attribute.value ) )
else
unixtime = new Date( attribute.value )
year = unixtime.getFullYear()
month = unixtime.getMonth() + 1
day = unixtime.getDate()
hour = unixtime.getHours()
minute = unixtime.getMinutes()
item = $( App.view('generic/datetime')(
attribute: attribute
year: year
month: month
day: day
hour: hour
minute: minute
) )
setNewTime = (diff, el, reset) ->
name = $(el).closest('.form-group').find('[data-name]').attr('data-name')
# remove old validation
item.find('.has-error').removeClass('has-error')
item.closest('.form-group').find('.help-inline').html('')
day = item.closest('.form-group').find("[name=\"{datetime}#{name}___day\"]").val()
month = item.closest('.form-group').find("[name=\"{datetime}#{name}___month\"]").val()
year = item.closest('.form-group').find("[name=\"{datetime}#{name}___year\"]").val()
hour = item.closest('.form-group').find("[name=\"{datetime}#{name}___hour\"]").val()
minute = item.closest('.form-group').find("[name=\"{datetime}#{name}___minute\"]").val()
format = (number) ->
if parseInt(number) < 10
number = "0#{number}"
number
if !reset && (year isnt '' && month isnt '' && day isnt '' && hour isnt '' && day isnt '')
time = new Date( Date.parse( "#{year}-#{format(month)}-#{format(day)}T#{format(hour)}:#{format(minute)}:00Z" ) )
time.setMinutes( time.getMinutes() + diff + time.getTimezoneOffset() )
else
time = new Date()
time.setMinutes( time.getMinutes() + diff )
#console.log('T', time, time.getHours(), time.getMinutes())
item.closest('.form-group').find("[name=\"{datetime}#{name}___day\"]").val( time.getDate() )
item.closest('.form-group').find("[name=\"{datetime}#{name}___month\"]").val( time.getMonth()+1 )
item.closest('.form-group').find("[name=\"{datetime}#{name}___year\"]").val( time.getFullYear() )
item.closest('.form-group').find("[name=\"{datetime}#{name}___hour\"]").val( time.getHours() )
item.closest('.form-group').find("[name=\"{datetime}#{name}___minute\"]").val( time.getMinutes() )
item.find('.js-today').bind('click', (e) ->
e.preventDefault()
setNewTime(0, @, true)
)
item.find('.js-plus-hour').bind('click', (e) ->
e.preventDefault()
setNewTime(60, @)
)
item.find('.js-minus-hour').bind('click', (e) ->
e.preventDefault()
setNewTime(-60, @)
)
item.find('.js-plus-day').bind('click', (e) ->
e.preventDefault()
setNewTime(60 * 24, @)
)
item.find('.js-minus-day').bind('click', (e) ->
e.preventDefault()
setNewTime(-60 * 24, @)
)
item.find('.js-plus-week').bind('click', (e) ->
e.preventDefault()
setNewTime(60 * 24 * 7, @)
)
item.find('.js-minus-week').bind('click', (e) ->
e.preventDefault()
setNewTime(-60 * 24 * 7, @)
)
item.find('input').bind('keyup blur focus change', (e) ->
# do validation
name = $(@).attr('name')
if name
fieldPrefix = name.split('___')[0]
# remove old validation
item.find('.has-error').removeClass('has-error')
item.closest('.form-group').find('.help-inline').html('')
day = item.closest('.form-group').find("[name=\"#{fieldPrefix}___day\"]").val()
month = item.closest('.form-group').find("[name=\"#{fieldPrefix}___month\"]").val()
year = item.closest('.form-group').find("[name=\"#{fieldPrefix}___year\"]").val()
hour = item.closest('.form-group').find("[name=\"#{fieldPrefix}___hour\"]").val()
minute = item.closest('.form-group').find("[name=\"#{fieldPrefix}___minute\"]").val()
# validate exists
errors = {}
if !day
errors.day = 'missing'
if !month
errors.month = 'missing'
if !year
errors.year = 'missing'
if !hour
errors.hour = 'missing'
if !minute
errors.minute = 'missing'
# ranges
if day
daysInMonth = 31
if month && year
daysInMonth = new Date(year, month, 0).getDate();
if parseInt(day).toString() is 'NaN'
errors.day = 'invalid'
else if parseInt(day) > daysInMonth || parseInt(day) < 1
errors.day = 'invalid'
if month
if parseInt(month).toString() is 'NaN'
errors.month = 'invalid'
else if parseInt(month) > 12 || parseInt(month) < 1
errors.month = 'invalid'
if year
if parseInt(year).toString() is 'NaN'
errors.year = 'invalid'
else if parseInt(year) > 2100 || parseInt(year) < 2001
errors.year = 'invalid'
if hour
if parseInt(hour).toString() is 'NaN'
errors.hour = 'invalid'
else if parseInt(hour) > 23 || parseInt(hour) < 0
errors.hour = 'invalid'
if minute
if parseInt(minute).toString() is 'NaN'
errors.minute = 'invalid'
else if parseInt(minute) > 59
errors.minute = 'invalid'
if !_.isEmpty(errors)
# if field is required, if not do not show error
if year is '' && day is '' && month is '' && hour is '' && minute is ''
if attribute.null
e.preventDefault()
e.stopPropagation()
return
else
item.closest('.form-group').find('.help-inline').text( 'is required' )
# show invalid options
for key, value of errors
item.closest('.form-group').addClass('has-error')
item.closest('.form-group').find("[name=\"#{fieldPrefix}___#{key}\"]").addClass('has-error')
#item.closest('.form-group').find('.help-inline').text( value )
e.preventDefault()
e.stopPropagation()
return
)
item

View file

@ -0,0 +1,176 @@
class App.UiElement.postmaster_match
@render: (attribute, params, form_controller) ->
addItem = (key, displayName, el, defaultValue = '') =>
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue }
itemInput = $( form_controller.formGenItem( add ).append('<svg class="icon icon-diagonal-cross remove"><use xlink:href="#icon-diagonal-cross"></use></svg>' ) )
# remove on click
itemInput.find('.remove').bind('click', (e) ->
e.preventDefault()
key = $(e.target).closest('.form-group').find('select, input').attr('name')
return if !key
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').show()
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').prop('disabled', false)
$(e.target).closest('.form-group').remove()
)
# add new item
control = el.closest('.postmaster_match')
control.find('.list').append(itemInput)
control.find('.addSelection select').val('')
control.find('.addSelection select option[value="' + key + '"]').prop('disabled', true)
control.find('.addSelection select option[value="' + key + '"]').hide()
# scaffold of match elements
item = $('
<div class="postmaster_match">
<hr>
<div class="list"></div>
<hr>
<div>
<div class="addSelection"></div>
<svg class="icon icon-plus add"><use xlink:href="#icon-plus"></use></svg>
</div>
</div>')
# select shown attributes
loopData = [
{
value: 'from'
name: 'From'
},
{
value: 'to'
name: 'To'
},
{
value: 'cc'
name: 'Cc'
},
{
value: 'subject'
name: 'Subject'
},
{
value: 'body'
name: 'Body'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-any-recipient'
name: 'Any Recipient'
},
{
value: ''
name: '-'
disable: true
},
{
value: ''
name: '- ' + App.i18n.translateInline('expert settings') + ' -'
disable: true
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-spam-flag'
name: 'X-Spam-Flag'
},
{
value: 'x-spam-level'
name: 'X-Spam-Level'
},
{
value: 'x-spam-score'
name: 'X-Spam-Score'
},
{
value: 'x-spam-status'
name: 'X-Spam-Status'
},
{
value: 'importance'
name: 'Importance'
},
{
value: 'x-priority'
name: 'X-Priority'
},
{
value: 'organization'
name: 'Organization'
},
{
value: 'x-original-to'
name: 'X-Original-To'
},
{
value: 'delivered-to'
name: 'Delivered-To'
},
{
value: 'envelope-to'
name: 'Envelope-To'
},
{
value: 'return-path'
name: 'Return-Path'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'list-id'
name: 'List-Id'
},
{
value: 'list-archive'
name: 'List-Archive'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'auto-submitted'
name: 'Auto-Submitted'
},
{
value: 'x-loop'
name: 'X-Loop'
},
]
for listItem in loopData
listItem.value = "#{ attribute.name }::#{listItem.value}"
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
item.find('.addSelection').append( form_controller.formGenItem( add ) )
# bind add click
item.find('.add').bind('click', (e) ->
e.preventDefault()
name = $(@).closest('.controls').find('.addSelection').find('select').val()
displayName = $(@).closest('.controls').find('.addSelection').find('select option:selected').html()
return if !name
addItem( name, displayName, $(@) )
)
# show default values
loopDataValue = {}
if attribute.value
for key, value of attribute.value
displayName = key
for listItem in loopData
if listItem.value is "#{ attribute.name }::#{key}"
addItem( "#{ attribute.name }::#{key}", listItem.name, item.find('.add'), value )
item

View file

@ -0,0 +1,124 @@
class App.UiElement.postmaster_set
@render: (attribute, params, form_controller) ->
addItem = (key, displayName, el, defaultValue = '') =>
collection = undefined
for listItem in loopData
if listItem.value is key
collection = listItem
if collection.relation
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, relation: collection.relation, translate: true, default: defaultValue }
else if collection.options
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, options: collection.options, translate: true, default: defaultValue }
else
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue }
itemInput = $( form_controller.formGenItem( add ).append('<svg class="icon icon-diagonal-cross remove"><use xlink:href="#icon-diagonal-cross"></use></svg>' ) )
# remove on click
itemInput.find('.remove').bind('click', (e) ->
e.preventDefault()
key = $(e.target).closest('.form-group').find('select, input').attr('name')
return if !key
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').show()
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').prop('disabled', false)
$(e.target).closest('.form-group').remove()
)
# add new item
control = el.closest('.perform_set')
control.find('.list').append(itemInput)
control.find('.addSelection select').val('')
control.find('.addSelection select option[value="' + key + '"]').prop('disabled', true)
control.find('.addSelection select option[value="' + key + '"]').hide()
# scaffold of perform elements
item = $('
<div class="perform_set">
<hr>
<div class="list"></div>
<hr>
<div>
<div class="addSelection"></div>
<svg class="icon icon-plus add"><use xlink:href="#icon-plus"></use></svg>
</div>
</div>')
# select shown attributes
loopData = [
{
value: 'x-zammad-ticket-priority_id'
name: 'Ticket Priority'
relation: 'TicketPriority'
},
{
value: 'x-zammad-ticket-state_id'
name: 'Ticket State'
relation: 'TicketState'
},
{
value: 'x-zammad-ticket-customer'
name: 'Ticket Customer'
},
{
value: 'x-zammad-ticket-group_id'
name: 'Ticket Group'
relation: 'Group'
},
{
value: 'x-zammad-ticket-owner'
name: 'Ticket Owner'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-zammad-article-internal'
name: 'Article Internal'
options: { true: 'Yes', false: 'No'}
},
{
value: 'x-zammad-article-type_id'
name: 'Article Type'
relation: 'TicketArticleType'
},
{
value: 'x-zammad-article-sender_id'
name: 'Article Sender'
relation: 'TicketArticleSender'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-zammad-ignore'
name: 'Ignore Message'
options: { true: 'Yes', false: 'No'}
},
]
for listItem in loopData
listItem.value = "#{ attribute.name }::#{listItem.value}"
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
item.find('.addSelection').append( form_controller.formGenItem( add ) )
item.find('.add').bind('click', (e) ->
e.preventDefault()
name = $(@).closest('.controls').find('.addSelection').find('select').val()
displayName = $(@).closest('.controls').find('.addSelection').find('select option:selected').html()
return if !name
addItem( name, displayName, $(@) )
)
# show default values
loopDataValue = {}
if attribute.value
for key, value of attribute.value
displayName = key
for listItem in loopData
if listItem.value is "#{ attribute.name }::#{key}"
addItem( "#{ attribute.name }::#{key}", listItem.name, item.find('.add'), value )
item

View file

@ -0,0 +1,25 @@
class App.UiElement.radio extends App.UiElement.ApplicationUiElement
@render: (attribute, params) ->
# build options list based on config
@getConfigOptionList( attribute, params )
# build options list based on relation
@getRelationOptionList( attribute, params )
# add null selection if needed
@addNullOption( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
# disable item of list
@disabledOptions( attribute, params )
# filter attributes
@filterOption( attribute, params )
$( App.view('generic/radio')( attribute: attribute ) )

View file

@ -0,0 +1,100 @@
class App.UiElement.richtext
@render: (attribute) ->
item = $( App.view('generic/richtext')( attribute: attribute ) )
item.find('[contenteditable]').ce(
mode: attribute.type
maxlength: attribute.maxlength
)
if attribute.upload
item.append( $( App.view('generic/attachment')( attribute: attribute ) ) )
renderAttachment = (file) =>
item.find('.attachments').append( App.view('generic/attachment_item')(
fileName: file.filename
fileSize: @humanFileSize( file.size )
store_id: file.store_id
))
item.on(
'click'
"[data-id=#{file.store_id}]", (e) =>
@attachments = _.filter(
@attachments,
(item) ->
return if item.id isnt file.store_id
item
)
store_id = $(e.currentTarget).data('id')
# delete attachment from storage
App.Ajax.request(
type: 'DELETE'
url: App.Config.get('api_path') + '/ticket_attachment_upload'
data: JSON.stringify( { store_id: store_id } ),
processData: false
success: (data, status, xhr) =>
)
# remove attachment from dom
element = $(e.currentTarget).closest('.attachments')
$(e.currentTarget).closest('.attachment').remove()
# empty .attachment (remove spaces) to keep css working, thanks @mrflix :-o
if element.find('.attachment').length == 0
element.empty()
)
@attachments = []
@progressBar = item.find('.attachmentUpload-progressBar')
@progressText = item.find('.js-percentage')
@attachmentPlaceholder = item.find('.attachmentPlaceholder')
@attachmentUpload = item.find('.attachmentUpload')
@attachmentsHolder = item.find('.attachments')
@cancelContainer = item.find('.js-cancel')
u = => html5Upload.initialize(
uploadUrl: App.Config.get('api_path') + '/ticket_attachment_upload',
dropContainer: item.closest('form').get(0),
cancelContainer: @cancelContainer,
inputField: item.find( 'input' ).get(0),
key: 'File',
data: { form_id: @form_id },
maxSimultaneousUploads: 1,
onFileAdded: (file) =>
file.on(
onStart: =>
@attachmentPlaceholder.addClass('hide')
@attachmentUpload.removeClass('hide')
@cancelContainer.removeClass('hide')
console.log('upload start')
onAborted: =>
@attachmentPlaceholder.removeClass('hide')
@attachmentUpload.addClass('hide')
# Called after received response from the server
onCompleted: (response) =>
response = JSON.parse(response)
@attachments.push response.data
@attachmentPlaceholder.removeClass('hide')
@attachmentUpload.addClass('hide')
renderAttachment(response.data)
console.log('upload complete', response.data )
# Called during upload progress, first parameter
# is decimal value from 0 to 100.
onProgress: (progress, fileSize, uploadedBytes) =>
@progressBar.width(parseInt(progress) + "%")
@progressText.text(parseInt(progress))
# hide cancel on 90%
if parseInt(progress) >= 90
@cancelContainer.addClass('hide')
console.log('uploadProgress ', parseInt(progress))
)
)
App.Delay.set( u, 100, undefined, 'form_upload' )
item

View file

@ -0,0 +1,3 @@
class App.UiElement.searchable_select
@render: (attribute) ->
new App.SearchableSelect( attribute: attribute ).element()

View file

@ -0,0 +1,32 @@
class App.UiElement.select extends App.UiElement.ApplicationUiElement
@render: (attribute, params, form_controller) ->
# set multible option
if attribute.multiple
attribute.multiple = 'multiple'
else
attribute.multiple = ''
# build options list based on config
@getConfigOptionList( attribute, params )
# build options list based on relation
@getRelationOptionList( attribute, params )
# add null selection if needed
@addNullOption( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
# disable item of list
@disabledOptions( attribute, params )
# filter attributes
@filterOption( attribute, params )
# return item
$( App.view('generic/select')( attribute: attribute ) )

View file

@ -0,0 +1,4 @@
class App.UiElement.sla_times
@render: (attribute) ->
$( App.view('generic/sla_times')( attribute: attribute ) )

View file

@ -0,0 +1,8 @@
class App.UiElement.tag
@render: (attribute) ->
item = $( App.view('generic/input')( attribute: attribute ) )
a = =>
$('#' + attribute.id ).tokenfield()
$('#' + attribute.id ).parent().css('height', 'auto')
App.Delay.set( a, 120, undefined, 'tags' )
item

View file

@ -0,0 +1,41 @@
class App.UiElement.textarea
@render: (attribute) ->
fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 )
item = $( App.view('generic/textarea')( attribute: attribute ) + '<div class="file-uploader ' + attribute.class + '" id="' + fileUploaderId + '"></div>' )
a = =>
visible = $( item[0] ).is(":visible")
if visible && !$( item[0] ).expanding('active')
$( item[0] ).expanding()
$( item[0] ).on('focus', ->
visible = $( item[0] ).is(":visible")
if visible && !$( item[0] ).expanding('active')
$( item[0] ).expanding().focus()
)
App.Delay.set( a, 80 )
if attribute.upload
# add file uploader
u = =>
# only add upload item if html element exists
if @el.find('#' + fileUploaderId )[0]
@el.find('#' + fileUploaderId ).fineUploader(
request:
endpoint: App.Config.get('api_path') + '/ticket_attachment_upload'
params:
form_id: @form_id
text:
uploadButton: '<i class="glyphicon glyphicon-paperclip"></i>'
template: '<div class="qq-uploader">' +
'<pre class="btn qq-upload-icon qq-upload-drop-area"><span>{dragZoneText}</span></pre>' +
'<div class="btn btn-default qq-upload-icon2 qq-upload-button pull-right" style="">{uploadButtonText}</div>' +
'<ul class="qq-upload-list span5" style="margin-top: 10px;"></ul>' +
'</div>',
classes:
success: ''
fail: ''
debug: false
)
App.Delay.set( u, 100, undefined, 'form_upload' )
item

View file

@ -0,0 +1,25 @@
class App.UiElement.timezone extends App.UiElement.ApplicationUiElement
@render: (attribute) ->
attribute.options = []
timezones = App.Config.get('timezones')
# build list based on config
for timezone_value, timezone_diff of timezones
if timezone_diff > 0
timezone_diff = '+' + timezone_diff
item =
name: "#{timezone_value} (GMT#{timezone_diff})"
value: timezone_value
attribute.options.push item
# add null selection if needed
@addNullOption( attribute, params )
# sort attribute.options
@sortOptions( attribute, params )
# finde selected/checked item of list
@selectedOptions( attribute, params )
$( App.view('generic/select')( attribute: attribute ) )

View file

@ -0,0 +1,3 @@
class App.UiElement.user_autocompletion
@render: (attribute) ->
new App.UserOrganizationAutocompletion( attribute: attribute ).element()

View file

@ -254,4 +254,6 @@ class App extends Spine.Controller
JST["app/views/#{name}"](params)
template
class App.UiElement
window.App = App