Fixes #2452 - Slow UI with over 150 ticket attributes.

This commit is contained in:
Martin Edenhofer 2019-01-29 08:06:47 +01:00
parent 46615333f9
commit 2cf614d302
6 changed files with 133 additions and 115 deletions

View file

@ -20,6 +20,10 @@ class App.ControllerForm extends App.Controller
if !@attributes if !@attributes
@attributes = [] @attributes = []
@idPrefix = Math.floor( Math.random() * 999999 ).toString()
if @model.className
@idPrefix = "#{@model.className}_#{@idPrefix}"
# set empty class attributes if needed # set empty class attributes if needed
if !@form if !@form
@form = @formGen() @form = @formGen()
@ -28,6 +32,12 @@ class App.ControllerForm extends App.Controller
@form.prepend('<div class="alert alert--danger js-danger js-alert hide" role="alert"></div>') @form.prepend('<div class="alert alert--danger js-danger js-alert hide" role="alert"></div>')
@form.prepend('<div class="alert alert--success js-success hide" role="alert"></div>') @form.prepend('<div class="alert alert--success js-success hide" role="alert"></div>')
if @handlers
params = App.ControllerForm.params(@form)
for attribute in @attributes
for handler in @handlers
handler(params, attribute, @attributes, @idPrefix, @form, @)
# if element is given, prepend form to it # if element is given, prepend form to it
if @el if @el
@el.prepend(@form) @el.prepend(@form)
@ -36,12 +46,6 @@ class App.ControllerForm extends App.Controller
if @elReplace if @elReplace
@elReplace.html(@form) @elReplace.html(@form)
# trigger change to rebuild shown/hidden item and update sub selections
if typeof @form is 'object'
@form.find('input').trigger('change')
@form.find('textarea').trigger('change')
@form.find('select').trigger('change')
# remove alert on input # remove alert on input
@form.on('input', @hideAlert) @form.on('input', @hideAlert)
@ -87,17 +91,16 @@ class App.ControllerForm extends App.Controller
@attributes.push attribute @attributes.push attribute
attribute_count = 0 attributeCount = 0
className = @model.className + '_' + Math.floor( Math.random() * 999999 ).toString()
for attribute in @attributes for attribute in @attributes
attribute_count = attribute_count + 1 attributeCount = attributeCount + 1
if @isDisabled == true if @isDisabled == true
attribute.disabled = true attribute.disabled = true
# add item # add item
item = @formGenItem(attribute, className, fieldset, attribute_count) item = @formGenItem(attribute, @idPrefix, fieldset, attributeCount)
item.appendTo(fieldset) item.appendTo(fieldset)
# if password, add confirm password item # if password, add confirm password item
@ -112,7 +115,7 @@ class App.ControllerForm extends App.Controller
if !attribute.single if !attribute.single
attribute.display = attribute.display + ' (confirm)' attribute.display = attribute.display + ' (confirm)'
attribute.name = attribute.name + '_confirm' attribute.name = attribute.name + '_confirm'
item = @formGenItem(attribute, className, fieldset, attribute_count) item = @formGenItem(attribute, @idPrefix, fieldset, attributeCount)
item.appendTo(fieldset) item.appendTo(fieldset)
if @fullForm if @fullForm
@ -125,7 +128,7 @@ class App.ControllerForm extends App.Controller
for eventSelector, callback of @events for eventSelector, callback of @events
do (eventSelector, callback) -> do (eventSelector, callback) ->
evs = eventSelector.split(' ') evs = eventSelector.split(' ')
fieldset.find( evs[1] ).bind( evs[0], (e) -> callback(e) ) fieldset.find(evs[1]).bind(evs[0], (e) -> callback(e))
# bind tool tips # bind tool tips
fieldset.find('.js-helpMessage').tooltip() fieldset.find('.js-helpMessage').tooltip()
@ -204,20 +207,19 @@ class App.ControllerForm extends App.Controller
class: 'medium' class: 'medium'
} }
### ###
formGenItem: (attribute_config, classname, form, attribute_count) -> formGenItem: (attribute_config, idPrefix, form, attributeCount) ->
attribute = clone(attribute_config, true) attribute = clone(attribute_config, true)
# create item id # create item id
attribute.id = "#{classname}_#{attribute.name}" attribute.id = "#{idPrefix}_#{attribute.name}"
# set label class name # set label class name
attribute.label_class = @model.labelClass attribute.label_class = @model.labelClass
# set autofocus # set autofocus
if @autofocus && attribute_count is 1 if @autofocus && attributeCount is 1
attribute.autofocus = 'autofocus' attribute.autofocus = 'autofocus'
# set required option # set required option
@ -281,13 +283,13 @@ class App.ControllerForm extends App.Controller
for item in attribute.options for item in attribute.options
if item.value && item.value isnt '' if item.value && item.value isnt ''
attributesNew.value = item.value attributesNew.value = item.value
item = $( App.view('generic/input')( attribute: attributesNew ) ) item = $( App.view('generic/input')(attribute: attributesNew) )
if @handlers if @handlers
item.bind('change', (e) => item.bind('change', (e) =>
params = App.ControllerForm.params( $(e.target) ) params = App.ControllerForm.params($(e.target))
for handler in @handlers for handler in @handlers
handler(params, attribute, @attributes, classname, form, @) handler(params, attribute, @attributes, idPrefix, form, @)
) )
# bind dependency # bind dependency
@ -376,7 +378,7 @@ class App.ControllerForm extends App.Controller
el.find('[name="' + key + '"]').attr('required', false) el.find('[name="' + key + '"]').attr('required', false)
el.find('[name="' + key + '"]').parents('.form-group').find('label span').html('') el.find('[name="' + key + '"]').parents('.form-group').find('label span').html('')
showHideToggle: (params, changedAttribute, attributes, classname, form, ui) -> showHideToggle: (params, changedAttribute, attributes, _classname, form, ui) ->
for attribute in attributes for attribute in attributes
if attribute.shown_if if attribute.shown_if
hit = false hit = false
@ -389,26 +391,26 @@ class App.ControllerForm extends App.Controller
else if params[refAttribute].toString() is refValue.toString() else if params[refAttribute].toString() is refValue.toString()
hit = true hit = true
if hit if hit
ui.show(attribute.name) ui.show(attribute.name, form)
else else
ui.hide(attribute.name) ui.hide(attribute.name, form)
requiredMandantoryToggle: (params, changedAttribute, attributes, classname, form, ui) -> requiredMandantoryToggle: (params, changedAttribute, attributes, _classname, form, ui) ->
for attribute in attributes for attribute in attributes
if attribute.required_if if attribute.required_if
hit = false hit = false
for refAttribute, refValue of attribute.required_if for refAttribute, refValue of attribute.required_if
if params[refAttribute] if params[refAttribute]
if _.isArray( refValue ) if _.isArray(refValue)
for item in refValue for item in refValue
if params[refAttribute].toString() is item.toString() if params[refAttribute].toString() is item.toString()
hit = true hit = true
else if params[refAttribute].toString() is refValue.toString() else if params[refAttribute].toString() is refValue.toString()
hit = true hit = true
if hit if hit
ui.mandantory(attribute.name) ui.mandantory(attribute.name, form)
else else
ui.optional(attribute.name) ui.optional(attribute.name, form)
validate: (params) -> validate: (params) ->
App.Model.validate( App.Model.validate(
@ -512,7 +514,7 @@ class App.ControllerForm extends App.Controller
param[newKey] = null param[newKey] = null
else if param[key] else if param[key]
try try
time = new Date( Date.parse( "#{param[key]}T00:00:00Z" ) ) time = new Date( Date.parse("#{param[key]}T00:00:00Z") )
format = (number) -> format = (number) ->
if parseInt(number) < 10 if parseInt(number) < 10
number = "0#{number}" number = "0#{number}"
@ -534,7 +536,7 @@ class App.ControllerForm extends App.Controller
param[newKey] = null param[newKey] = null
else if param[key] else if param[key]
try try
time = new Date( Date.parse( param[key] ) ) time = new Date( Date.parse(param[key]) )
if time is 'Invalid Datetime' if time is 'Invalid Datetime'
throw "Invalid Datetime #{param[key]}" throw "Invalid Datetime #{param[key]}"
param[newKey] = time.toISOString().replace(/:\d\d\.\d\d\dZ$/, ':00.000Z') param[newKey] = time.toISOString().replace(/:\d\d\.\d\d\dZ$/, ':00.000Z')

View file

@ -14,12 +14,13 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
item = $(App.view('object_manager/attribute')(attribute: attribute)) item = $(App.view('object_manager/attribute')(attribute: attribute))
updateDataMap = (localParams, localAttribute, localAttributes, localClassname, localForm, localA) => updateDataMap = (localParams, localAttribute, localAttributes, localClassname, localForm, localA) =>
localItem = localForm.closest('.js-data') return if !localParams.data_type
element = $(App.view("object_manager/attribute/#{localParams.data_type}")( element = $(App.view("object_manager/attribute/#{localParams.data_type}")(
attribute: attribute attribute: attribute
params: params params: params
)) ))
@[localParams.data_type](element, localParams, params, attribute) @[localParams.data_type](element, localParams, params, attribute)
localItem = localForm.closest('.js-data')
localItem.find('.js-dataMap').html(element) localItem.find('.js-dataMap').html(element)
localItem.find('.js-dataScreens').html(@dataScreens(attribute, localParams, params)) localItem.find('.js-dataScreens').html(@dataScreens(attribute, localParams, params))
@ -42,6 +43,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
{ name: attribute.name, display: '', tag: 'select', null: false, options: options, translate: true, default: 'input', disabled: attribute.disabled }, { name: attribute.name, display: '', tag: 'select', null: false, options: options, translate: true, default: 'input', disabled: attribute.disabled },
] ]
dataType = new App.ControllerForm( dataType = new App.ControllerForm(
el: item.find('.js-dataType')
model: model:
configure_attributes: configureAttributes configure_attributes: configureAttributes
noFieldset: true noFieldset: true
@ -50,8 +52,8 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
] ]
params: params params: params
) )
item.find('.js-dataType').html(dataType.form)
item.find('.js-boolean').data('field-type', 'boolean') item.find('.js-boolean').data('field-type', 'boolean')
item.find('.js-dataType [name="data_type"]').trigger('change')
item item
@dataScreens: (attribute, localParams, params) -> @dataScreens: (attribute, localParams, params) ->

View file

@ -26,8 +26,13 @@ class App.UiElement.permission extends App.UiElement.ApplicationUiElement
) ) ) )
# show/hide trees # show/hide trees
item.find('[name=permission_ids]').bind('change', (e) -> item.find('[name=permission_ids]').bind('change', (e) =>
element = $(e.currentTarget) @checkUncheck($(e.currentTarget), permissions, item)
)
item.find('[name=permission_ids]').trigger('change')
item
@checkUncheck: (element, permissions, item) ->
checked = element.prop('checked') checked = element.prop('checked')
permission_id = element.prop('value') permission_id = element.prop('value')
return if !permission_id return if !permission_id
@ -50,6 +55,3 @@ class App.UiElement.permission extends App.UiElement.ApplicationUiElement
if lookupPermission if lookupPermission
item.find("[name=permission_ids][value=#{lookupPermission.id}]").prop('checked', false) item.find("[name=permission_ids][value=#{lookupPermission.id}]").prop('checked', false)
)
item

View file

@ -142,7 +142,7 @@ class App.UiElement.postmaster_match
selector = @buildAttributeSelector(groups, attribute) selector = @buildAttributeSelector(groups, attribute)
# scaffold of match elements # scaffold of match elements
item = $( App.view('generic/postmaster_match')( attribute: attribute ) ) item = $( App.view('generic/postmaster_match')(attribute: attribute) )
item.find('.js-attributeSelector').prepend(selector) item.find('.js-attributeSelector').prepend(selector)
# add filter # add filter
@ -163,7 +163,6 @@ class App.UiElement.postmaster_match
item.find('.js-attributeSelector select').bind('change', (e) => item.find('.js-attributeSelector select').bind('change', (e) =>
key = $(e.target).find('option:selected').attr('value') key = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement') elementRow = $(e.target).closest('.js-filterElement')
@rebuildAttributeSelectors(item, elementRow, key, attribute) @rebuildAttributeSelectors(item, elementRow, key, attribute)
@rebuildOperater(item, elementRow, key, groups, undefined, attribute) @rebuildOperater(item, elementRow, key, groups, undefined, attribute)
@buildValue(item, elementRow, key, groups, undefined, undefined, attribute) @buildValue(item, elementRow, key, groups, undefined, undefined, attribute)
@ -178,8 +177,9 @@ class App.UiElement.postmaster_match
) )
# build inital params # build inital params
if !_.isEmpty(params[attribute.name]) if _.isEmpty(params[attribute.name])
item.find('.js-filterElement .js-attributeSelector select').trigger('change')
else
selectorExists = false selectorExists = false
for key, meta of params[attribute.name] for key, meta of params[attribute.name]
selectorExists = true selectorExists = true
@ -197,6 +197,8 @@ class App.UiElement.postmaster_match
@buildValue(item, elementClone, key, groups, value, operator, attribute) @buildValue(item, elementClone, key, groups, value, operator, attribute)
elementLast.after(elementClone) elementLast.after(elementClone)
item.find('.js-attributeSelector select').trigger('change')
# remove first dummy row # remove first dummy row
if selectorExists if selectorExists
item.find('.js-filterElement').first().remove() item.find('.js-filterElement').first().remove()

View file

@ -115,7 +115,7 @@ class App.UiElement.postmaster_set
[elements, groups] [elements, groups]
@placeholder: (elementFull, attribute, params = {}, groups) -> @placeholder: (elementFull, attribute, params = {}, groups) ->
item = $( App.view('generic/postmaster_set_row')( attribute: attribute ) ) item = $( App.view('generic/postmaster_set_row')(attribute: attribute) )
selector = @buildAttributeSelector(elementFull, groups, attribute, item) selector = @buildAttributeSelector(elementFull, groups, attribute, item)
item.find('.js-attributeSelector').prepend(selector) item.find('.js-attributeSelector').prepend(selector)
item item
@ -125,7 +125,7 @@ class App.UiElement.postmaster_set
[elements, groups] = @defaults() [elements, groups] = @defaults()
# scaffold of match elements # scaffold of match elements
item = $( App.view('generic/postmaster_set')( attribute: attribute ) ) item = $( App.view('generic/postmaster_set')(attribute: attribute) )
# add filter # add filter
item.on('click', '.js-add', (e) => item.on('click', '.js-add', (e) =>
@ -147,29 +147,37 @@ class App.UiElement.postmaster_set
# change attribute selector # change attribute selector
item.on('change', '.js-attributeSelector select', (e) => item.on('change', '.js-attributeSelector select', (e) =>
key = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement') elementRow = $(e.target).closest('.js-filterElement')
groupAndAttribute = elementRow.find('.js-attributeSelector option:selected').attr('value') groupAndAttribute = elementRow.find('.js-attributeSelector option:selected').attr('value')
@rebuildAttributeSelectors(item, elementRow, key, attribute) @rebuildAttributeSelectors(item, elementRow, groupAndAttribute, attribute)
@buildOperator(item, elementRow, groupAndAttribute, elements, {}, attribute) @buildOperator(item, elementRow, groupAndAttribute, elements, {}, attribute)
@buildValue(item, elementRow, key, groups, undefined, undefined, attribute) @buildValue(item, elementRow, groupAndAttribute, groups, undefined, undefined, attribute)
) )
# build inital params # build inital params
if _.isEmpty(params[attribute.name]) if _.isEmpty(params[attribute.name])
item.append(@placeholder(item, attribute, params, groups)) element = @placeholder(item, attribute, params, groups)
item.append(element)
groupAndAttribute = element.find('.js-attributeSelector option:selected').attr('value')
@rebuildAttributeSelectors(item, element, groupAndAttribute, attribute)
@buildOperator(item, element, groupAndAttribute, elements, {}, attribute)
@buildValue(item, element, groupAndAttribute, groups, undefined, undefined, attribute)
return item return item
else
for key, meta of params[attribute.name] for key, meta of params[attribute.name]
operator = meta.operator operator = meta.operator
value = meta.value value = meta.value
# build and append # build and append
element = @placeholder(item, attribute, params, groups) element = @placeholder(item, attribute, params, groups)
groupAndAttribute = element.find('.js-attributeSelector option:selected').attr('value')
@rebuildAttributeSelectors(item, element, key, attribute) @rebuildAttributeSelectors(item, element, key, attribute)
@buildOperator(item, element, key, elements, {}, attribute)
@buildValue(item, element, key, groups, value, operator, attribute) @buildValue(item, element, key, groups, value, operator, attribute)
item.append(element) item.append(element)
item.find('.js-attributeSelector select').trigger('change')
item item

View file

@ -96,8 +96,13 @@ class App.UiElement.user_permission
item.on('click', '.checkbox-replacement', throttled) item.on('click', '.checkbox-replacement', throttled)
# if customer, remove admin and agent # if customer, remove admin and agent
item.find('[name=role_ids]').bind('change', (e) -> item.find('[name=role_ids]').bind('change', (e) =>
element = $(e.currentTarget) @checkUncheck($(e.currentTarget), rolesWithGroupPlugin, item, hideGroups)
)
item.find('[name=role_ids]').trigger('change')
item
@checkUncheck: (element, rolesWithGroupPlugin, item, hideGroups) ->
checked = element.prop('checked') checked = element.prop('checked')
role_id = element.prop('value') role_id = element.prop('value')
return if !role_id return if !role_id
@ -143,6 +148,3 @@ class App.UiElement.user_permission
for trigger in triggers for trigger in triggers
trigger.trigger('change') trigger.trigger('change')
)
item