Browse Source

Init version of object manager.

Martin Edenhofer 10 years ago
parent
commit
c4c4ef35ef

+ 139 - 91
app/assets/javascripts/app/controllers/_application_controller_form.js.coffee

@@ -2,7 +2,11 @@ class App.ControllerForm extends App.Controller
   constructor: (params) ->
     for key, value of params
       @[key] = value
-    @attribute_count = 0
+
+    if !@handlers
+      @handlers = []
+    @handlers.push @_showHideToggle
+    @handlers.push @_requiredMandantoryToggle
 
     if !@form
       @form = @formGen()
@@ -23,37 +27,62 @@ class App.ControllerForm extends App.Controller
 
     fieldset = $('<fieldset></fieldset>')
 
-    for attribute_clean in @model.configure_attributes
-      attribute = _.clone( attribute_clean )
+    # collect form attributes
+    @attributes = []
+    if @model.attributesGet
+      attributesClean = @model.attributesGet(@screen)
+    else
+      attributesClean = App.Model.attributesGet(@screen, @model.configure_attributes )
+
+    for attributeName, attribute of attributesClean
+
+      # ignore read only attributes
+      if !attribute.readonly
+
+        # check generic filter
+        if @filter && !attribute.filter
+          if @filter[ attributeName ]
+            attribute.filter = @filter[ attributeName ]
 
-      if !attribute.readonly && ( !@required || @required && attribute[@required] )
+        @attributes.push attribute
 
-        @attribute_count = @attribute_count + 1
+    attribute_count = 0
+    className       = @model.className + '_' + Math.floor( Math.random() * 999999 ).toString()
 
-        # add item
-        item = @formGenItem( attribute, @model.className, fieldset )
-        item.appendTo(fieldset)
+    for attribute in @attributes
+      attribute_count = attribute_count + 1
 
-        # if password, add confirm password item
-        if attribute.type is 'password'
+      # add item
+      item = @formGenItem( attribute, className, fieldset, attribute_count )
+      item.appendTo(fieldset)
 
-          # set selected value passed on current params
-          if @params
-            if attribute.name of @params
-              attribute.value = @params[attribute.name]
+      # if password, add confirm password item
+      if attribute.type is 'password'
 
-          # rename display and name to _confirm
-          if !attribute.single
-            attribute.display = attribute.display + ' (confirm)'
-            attribute.name = attribute.name + '_confirm';
-            item = @formGenItem( attribute, @model.className, fieldset )
-            item.appendTo(fieldset)
+        # 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 !@formClass
         @formClass = ''
       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 fieldset
 
@@ -131,14 +160,14 @@ class App.ControllerForm extends App.Controller
 
   ###
 
-  formGenItem: (attribute_config, classname, form ) ->
-    attribute = _.clone( attribute_config )
+  formGenItem: (attribute_config, classname, form, attribute_count ) ->
+    attribute = clone( attribute_config )
 
     # create item id
     attribute.id = classname + '_' + attribute.name
 
     # set autofocus
-    if @autofocus && @attribute_count is 1
+    if @autofocus && attribute_count is 1
       attribute.autofocus = 'autofocus'
 
     # set required option
@@ -234,6 +263,22 @@ class App.ControllerForm extends App.Controller
     else if attribute.tag is 'select'
       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
     else if attribute.tag is 'timezone'
       attribute.options = []
@@ -717,7 +762,7 @@ class App.ControllerForm extends App.Controller
 
         b = (event, item) =>
           # set html form attribute
-          $(local_attribute).val(item.id)
+          $(local_attribute).val(item.id).trigger('change')
           $(local_attribute + '_autocompletion_value_shown').val(item.value)
 
           # 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(
-          source: attribute.source,
+          source: source,
           minLength: attribute.minLengt || 3,
           select: ( event, ui ) =>
             b(event, ui.item)
@@ -1221,63 +1269,12 @@ class App.ControllerForm extends App.Controller
     else
       item = $( App.view('generic/input')( attribute: attribute ) )
 
-    if attribute.onchange
-      if typeof attribute.onchange is 'function'
-        attribute.onchange(attribute)
-      else
-        for i of attribute.onchange
-          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 )
-    )
+    if @handlers
+      item.bind('change', (e) =>
+        params = App.ControllerForm.params( $(e.target) )
+        for handler in @handlers
+          handler(params, attribute, @attributes, classname, form, @)
+      )
 
     # bind 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 + '"]').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
   _sortOptions: (attribute) ->
 
@@ -1399,6 +1434,7 @@ class App.ControllerForm extends App.Controller
 
     list = []
     if attribute.filter
+
       App.Log.debug 'ControllerForm', '_getRelationOptionList:filter', attribute.filter
 
       # function based filter
@@ -1426,6 +1462,22 @@ class App.ControllerForm extends App.Controller
             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
+              list.push record
+
       # no data filter matched
       else
         App.Log.debug 'ControllerForm', '_getRelationOptionList:filter-data no filter matched'
@@ -1512,8 +1564,9 @@ class App.ControllerForm extends App.Controller
 
   validate: (params) ->
     App.Model.validate(
-      model: @model,
-      params: params,
+      model:  @model
+      params: params
+      screen: @screen
     )
 
   # get all params of the form
@@ -1637,13 +1690,8 @@ class App.ControllerForm extends App.Controller
 
     # show new 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 + '"]').parent().find('.help-inline').html(msg)
+      $(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)
 
     # set autofocus
     $(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)
-

+ 6 - 6
app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee

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

+ 4 - 3
app/assets/javascripts/app/controllers/_application_controller_table.js.coffee

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

+ 89 - 46
app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee

@@ -14,7 +14,7 @@ class App.TicketCreate extends App.Controller
     # set title
     @form_id = App.ControllerForm.formId()
 
-    @edit_form = undefined
+    @form_meta = undefined
 
     # set article attributes
     default_type = 'call_inbound'
@@ -25,14 +25,17 @@ class App.TicketCreate extends App.Controller
         sender:  'Customer'
         article: 'phone'
         title:   'Call Inbound'
+        screen:  'create_phone_in'
       call_outbound:
         sender:  'Agent'
         article: 'phone'
         title:   'Call Outbound'
+        screen:  'create_phone_out'
       email:
         sender:  'Agent'
         article: 'email'
         title:   'Email'
+        screen:  'create_email_out'
     @article_attributes = article_sender_type_map[@type]
 
     # remember split info if exists
@@ -57,9 +60,9 @@ class App.TicketCreate extends App.Controller
 
   meta: =>
     text = App.i18n.translateInline( @article_attributes['title'] )
-    subject = @el.find('[name=subject]').val()
-    if subject
-      text = "#{text}: #{subject}"
+    title = @el.find('[name=title]').val()
+    if title
+      text = "#{text}: #{title}"
     meta =
       url:   @url()
       head:  text
@@ -100,7 +103,7 @@ class App.TicketCreate extends App.Controller
     if cache && !params.ticket_id && !params.article_id
 
       # get edit form attributes
-      @edit_form = cache.edit_form
+      @form_meta = cache.form_meta
 
       # load assets
       App.Collection.loadAssets( cache.assets )
@@ -108,7 +111,7 @@ class App.TicketCreate extends App.Controller
       @render()
     else
       @ajax(
-        id:    'ticket_create'
+        id:    'ticket_create' + @task_key
         type:  'GET'
         url:   @apiPath + '/ticket_create'
         data:
@@ -121,7 +124,7 @@ class App.TicketCreate extends App.Controller
           App.Store.write( 'ticket_create_attributes', data )
 
           # get edit form attributes
-          @edit_form = data.edit_form
+          @form_meta = data.form_meta
 
           # load assets
           App.Collection.loadAssets( data.assets )
@@ -143,22 +146,6 @@ class App.TicketCreate extends App.Controller
 
   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')(
       head:  'New Ticket'
       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 )
       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(
-      el: @el.find('.ticket_create')
-      form_id: @form_id
-      model:
-        configure_attributes: configure_attributes
-        className:            'create_' + @type + '_' + @id
+      el:       @el.find('.ticket-form')
+      form_id:  @form_id
+      model:    App.Ticket
+      screen:   @article_attributes['screen']
+      events:
+        'change [name=customer_id]': @localUserInfo
+      handlers: [
+        formChanges
+      ]
+      filter:     @form_meta.filter
       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
     )
 
@@ -193,20 +216,23 @@ class App.TicketCreate extends App.Controller
 
     # show text module UI
     @textModule = new App.WidgetTextModule(
-      el: @el.find('.ticket-create').find('textarea')
+      el: @el.find('form').find('textarea')
     )
 
     # start auto save
     @autosave()
 
-  localUserInfo: (params) =>
+  localUserInfo: (e) =>
+
+    params = App.ControllerForm.params( $(e.target).closest('form') )
 
     # update text module UI
     callback = (user) =>
-      @textModule.reload(
-        ticket:
-          customer: user
-      )
+      if @textModule
+        @textModule.reload(
+          ticket:
+            customer: user
+        )
 
     @userInfo(
       user_id:  params.customer_id
@@ -234,7 +260,7 @@ class App.TicketCreate extends App.Controller
       params.title = params.subject
 
     # create ticket
-    object = new App.Ticket
+    ticket = new App.Ticket
 
     # find sender_id
     sender = App.TicketArticleSender.findByAttribute( 'name', @article_attributes['sender'] )
@@ -248,6 +274,7 @@ class App.TicketCreate extends App.Controller
       params['article'] = {
         to:         (group && group.name) || ''
         from:       params.customer_id_autocompletion
+        cc:         params.cc
         subject:    params.subject
         body:       params.body
         type_id:    type.id
@@ -258,6 +285,7 @@ class App.TicketCreate extends App.Controller
       params['article'] = {
         from:       (group && group.name) || ''
         to:         params.customer_id_autocompletion
+        cc:         params.cc
         subject:    params.subject
         body:       params.body
         type_id:    type.id
@@ -265,15 +293,30 @@ class App.TicketCreate extends App.Controller
         form_id:    @form_id
       }
 
-    object.load(params)
+    ticket.load(params)
 
     # 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
-    if errors
-      @log 'error', errors
-      @formValidate( form: e.target, errors: errors )
+    if ticketErrors
+      @log 'error', ticketErrors
+      @formValidate(
+        form: e.target
+        errors: ticketErrors
+        screen: @article_attributes['screen']
+      )
 
     # save ticket, create article
     else
@@ -281,7 +324,7 @@ class App.TicketCreate extends App.Controller
       # disable form
       @formDisable(e)
       ui = @
-      object.save(
+      ticket.save(
         done: ->
 
           # notify UI
@@ -322,10 +365,10 @@ class UserNew extends App.ControllerModal
     @html App.view('agent_user_create')( head: 'New User' )
 
     new App.ControllerForm(
-      el: @el.find('#form-user'),
-      model: App.User,
-      required: 'quick',
-      autofocus: true,
+      el:         @el.find('#form-user')
+      model:      App.User
+      screen:     'edit'
+      autofocus:  true
     )
 
     @modalShow()

+ 39 - 37
app/assets/javascripts/app/controllers/customer_ticket_create.js.coffee

@@ -16,8 +16,6 @@ class Index extends App.ControllerContent
     @fetch(params)
     @navupdate '#customer_ticket_new'
 
-    @edit_form = undefined
-
   # get data / in case also ticket data for split
   fetch: (params) ->
 
@@ -26,9 +24,6 @@ class Index extends App.ControllerContent
 
     if cache
 
-      # get edit form attributes
-      @edit_form = cache.edit_form
-
       # load assets
       App.Collection.loadAssets( cache.assets )
 
@@ -44,9 +39,6 @@ class Index extends App.ControllerContent
           # cache request
           App.Store.write( 'ticket_create_attributes', data )
 
-          # get edit form attributes
-          @edit_form = data.edit_form
-
           # load 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() )
       )
 
-    # 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' )
 
     new App.ControllerForm(
-      el:      @el.find('#form_create')
-      form_id: @form_id
-      model:
-        configure_attributes: configure_attributes
-        className:            'create'
+      el:       @el.find('.ticket-form')
+      form_id:  @form_id
+      model:    App.Ticket
+      screen:   'create_web'
       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(
@@ -128,19 +120,21 @@ class Index extends App.ControllerContent
     params.customer_id = @Session.get('id')
 
     # set prio
-    priority = App.TicketPriority.findByAttribute( 'name', '2 normal' )
-    params.priority_id = priority.id
+    if !params.priority_id
+      priority = App.TicketPriority.findByAttribute( 'name', '2 normal' )
+      params.priority_id = priority.id
 
     # set state
-    state = App.TicketState.findByAttribute( 'name', 'new' )
-    params.state_id = state.id
+    if !params.state_id
+      state = App.TicketState.findByAttribute( 'name', 'new' )
+      params.state_id = state.id
 
     # fillup params
     if !params.title
       params.title = params.subject
 
     # create ticket
-    object = new App.Ticket
+    ticket = new App.Ticket
     @log 'CustomerTicketCreate', 'notice', 'updateAttributes', params
 
     # find sender_id
@@ -160,16 +154,27 @@ class Index extends App.ControllerContent
       form_id:    @form_id
     }
 
-    object.load(params)
+    ticket.load(params)
 
     # 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
-    if errors
-      @log 'CustomerTicketCreate', 'error', 'can not create', errors
+    if ticketErrors
+      @log 'CustomerTicketCreate', 'error', 'can not create', ticketErrors
 
-      @formValidate( form: e.target, errors: errors )
+      @formValidate( form: e.target, errors: ticketErrors )
 
     # save ticket, create article
     else
@@ -177,7 +182,7 @@ class Index extends App.ControllerContent
       # disable form
       @formDisable(e)
       ui = @
-      object.save(
+      ticket.save(
         done: ->
 
           # redirect to zoom
@@ -189,7 +194,4 @@ class Index extends App.ControllerContent
       )
 
 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' )
-

+ 1 - 1
app/assets/javascripts/app/controllers/signup.js.coffee

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

+ 85 - 56
app/assets/javascripts/app/controllers/ticket_zoom.js.coffee

@@ -7,7 +7,7 @@ class App.TicketZoom extends App.Controller
 
     @navupdate '#'
 
-    @edit_form      = undefined
+    @form_meta      = undefined
     @ticket_id      = params.ticket_id
     @article_id     = params.article_id
     @signature      = undefined
@@ -111,7 +111,7 @@ class App.TicketZoom extends App.Controller
     @ticket_article_ids = data.ticket_article_ids
 
     # get edit form attributes
-    @edit_form = data.edit_form
+    @form_meta = data.form_meta
 
     # get signature
     @signature = data.signature
@@ -181,7 +181,7 @@ class App.TicketZoom extends App.Controller
     new Edit(
       ticket:     @ticket
       el:         @el.find('.edit')
-      edit_form:  @edit_form
+      form_meta:  @form_meta
       task_key:   @task_key
       ui:         @
     )
@@ -331,57 +331,55 @@ class Edit extends App.Controller
       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()
-    defaults = ticket
+    defaults = ticket.attributes()
+    if @isRole('Customer')
+      delete defaults['state_id']
+      delete defaults['state']
     if !_.isEmpty( App.TaskManager.get(@task_key).state )
       defaults = 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(
-      el:        @el.find('.form-ticket-update')
-      form_id:   @form_id
-      model:
-        configure_attributes: @configure_attributes_ticket
-        className:            'update_ticket_' + ticket.id
+      el:       @el.find('.form-ticket-update')
+      form_id:  @form_id
+      model:    App.Ticket
+      screen:   'edit'
+      handlers: [
+        formChanges
+      ]
+      filter:    @form_meta.filter
       params:    defaults
-      form_data: @edit_form
     )
-
     new App.ControllerForm(
       el:        @el.find('.form-article-update')
       form_id:   @form_id
-      model:
-        configure_attributes: @configure_attributes_article
-        className:            'update_ticket_' + ticket.id
-      form_data: @edit_form
+      model:     App.TicketArticle
+      screen:   'edit'
+      filter:
+        type_id: [1,9,5]
       params:    defaults
       dependency: [
         {
@@ -399,13 +397,24 @@ class Edit extends App.Controller
           bind: {
             name:     'type_id'
             relation: 'TicketArticleType'
-            value:    ['note', 'twitter status', 'twitter direct-message']
+            value:    ['note', 'phone', 'twitter status']
           },
           change: {
             action: 'hide'
             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()
     params = @formParam(e.target)
 
+    # get ticket
     ticket = App.Ticket.fullLocal( @ticket.id )
 
     @log 'notice', 'update', params, ticket
 
+    # update local ticket
+
+    # create local article
+
+
     # find sender_id
     if @isRole('Customer')
       sender            = App.TicketArticleSender.findByAttribute( 'name', 'Customer' )
@@ -469,17 +484,16 @@ class Edit extends App.Controller
       params.sender_id  = sender.id
 
     # update ticket
-    ticket_update = {}
-    for item in @configure_attributes_ticket
-      ticket_update[item.name] = params[item.name]
+    for key, value of params
+      ticket[key] = value
 
     # check owner assignment
     if !@isRole('Customer')
-      if !ticket_update['owner_id']
-        ticket_update['owner_id'] = 1
+      if !ticket['owner_id']
+        ticket['owner_id'] = 1
 
     # check if title exists
-    if !ticket_update['title'] && !ticket.title
+    if !ticket['title']
       alert( App.i18n.translateContent('Title needed') )
       return
 
@@ -505,22 +519,32 @@ class Edit extends App.Controller
           @autosaveStart()
           return
 
-    ticket.load( ticket_update )
-    @log 'notice', 'update ticket', ticket_update, ticket
+    # submit ticket & article
+    @log 'notice', 'update ticket', ticket
 
     # disable form
     @formDisable(e)
 
     # validate ticket
-    errors = ticket.validate()
+    errors = ticket.validate(
+      screen: 'edit'
+    )
     if errors
       @log 'error', 'update', errors
+
+      @log 'error', errors
+      @formValidate(
+        form:   e.target
+        errors: errors
+        screen: 'edit'
+      )
       @formEnable(e)
       @autosaveStart()
       return
 
     # validate article
-    if params['body']
+    articleAttributes = App.TicketArticle.attributesGet( 'edit' )
+    if params['body'] || ( articleAttributes['body'] && articleAttributes['body']['null'] is false )
       article = new App.TicketArticle
       params.from      = @Session.get( 'firstname' ) + ' ' + @Session.get( 'lastname' )
       params.ticket_id = ticket.id
@@ -534,6 +558,11 @@ class Edit extends App.Controller
       errors = article.validate()
       if errors
         @log 'error', 'update article', errors
+        @formValidate(
+          form:   e.target
+          errors: errors
+          screen: 'edit'
+        )
         @formEnable(e)
         @autosaveStart()
         return

+ 7 - 8
app/assets/javascripts/app/controllers/widget/user.js.coffee

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

+ 14 - 1
app/assets/javascripts/app/lib/app_post/auth.js.coffee

@@ -69,12 +69,26 @@ class App.Auth
       App.Event.trigger( 'auth:logout' )
       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;
 
     # clear local store
     if type isnt 'check'
       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
     for key, value of data.config
       App.Config.set( key, value )
@@ -129,4 +143,3 @@ class App.Auth
     App.Event.trigger( 'auth:logout' )
     App.Event.trigger( 'ui:rerender' )
     App.Event.trigger( 'clearStore' )
-

+ 49 - 19
app/assets/javascripts/app/models/_application_model.js.coffee

@@ -64,19 +64,17 @@ class App.Model extends Spine.Model
     return '???'
 
   @validate: ( data = {} ) ->
-    attributes = _.clone( data['model'].configure_attributes )
-    return if !attributes
 
-    # check params of screen if screen is requested
-    if data['screen']
-      for attribute in attributes
-        if attribute.screen
-          if attribute && attribute.screen && attribute.screen[ data['screen'] ] && !_.isEmpty(attribute.screen[ data['screen'] ])
-            for item, value of attribute.screen[ data['screen'] ]
-              attribute[item] = value
+    # based on model attrbutes
+    if App[ data['model'] ] && App[ data['model'] ].attributesGet
+      attributes = App[ data['model'] ].attributesGet( data['screen'] )
+
+    # based on custom attributes
+    else if data['model'].configure_attributes
+      attributes = App.Model.attributesGet( data['screen'], data['model'].configure_attributes )
 
     # check required_if attributes
-    for attribute in attributes
+    for attributeName, attribute of attributes
       if 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
     errors = {}
-    for attribute in attributes
+    for attributeName, attribute of attributes
 
       # only if attribute is not read only
       if !attribute.readonly
@@ -111,25 +109,25 @@ class App.Model extends Spine.Model
           if parts[0] && !parts[1]
 
             # 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
-              errors[attribute.name] = 'is required'
+            if !( attributeName of data['params'] ) || data['params'][attributeName] is '' || data['params'][attributeName] is undefined
+              errors[attributeName] = 'is required'
 
           else if parts[0] && parts[1] && !parts[2]
 
             # 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
-              errors[attribute.name] = 'is required'
+              errors[attributeName] = 'is required'
 
           else
             throw "can't parse '#{attribute.name}'"
 
         # 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
-          if data['params'][attribute.name] isnt data['params']["#{attribute.name}_confirm"]
-            errors[attribute.name] = 'didn\'t match'
-            errors["#{attribute.name}_confirm"] = ''
+          if data['params'][attributeName] isnt data['params']["#{attributeName}_confirm"]
+            errors[attributeName] = 'didn\'t match'
+            errors["#{attributeName}_confirm"] = ''
 
     # return error object
     if !_.isEmpty(errors)
@@ -139,9 +137,41 @@ class App.Model extends Spine.Model
     # return no errors
     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 = {}) ->
     App.Model.validate(
-      model: @constructor
+      model:  @constructor.className
       params: @
       screen: params.screen
     )

Some files were not shown because too many files changed in this diff