Browse Source

Added central formDiff() method. Fixed clone() and added tests.

Martin Edenhofer 10 years ago
parent
commit
a7a41d201d

+ 6 - 2
app/assets/javascripts/app/controllers/_application_controller_form.js.coffee

@@ -2324,7 +2324,9 @@ class App.ControllerForm extends App.Controller
           month       = param[ "#{dateKey}month" ]
           day         = param[ "#{dateKey}day" ]
           timezone    = (new Date()).getTimezoneOffset()/60
-          if year && month && day && day && !lookupForm.find('[data-name="' + namespace[0] + '"]').hasClass('is-hidden')
+          if lookupForm.find('[data-name="' + namespace[0] + '"]').hasClass('is-hidden')
+            param[ namespace[0] ] = null
+          else if year && month && day && day
             format = (number) ->
               if parseInt(number) < 10
                 number = "0#{number}"
@@ -2360,7 +2362,9 @@ class App.ControllerForm extends App.Controller
           hour        = param[ "#{datetimeKey}hour" ]
           minute      = param[ "#{datetimeKey}minute" ]
           timezone    = (new Date()).getTimezoneOffset()/60
-          if year && month && day && hour && minute && !lookupForm.find('[data-name="' + namespace[0] + '"]').hasClass('is-hidden')
+          if lookupForm.find('[data-name="' + namespace[0] + '"]').hasClass('is-hidden')
+            param[ namespace[0] ] = null
+          else if year && month && day && hour && minute
             format = (number) ->
               if parseInt(number) < 10
                 number = "0#{number}"

+ 56 - 1
app/assets/javascripts/app/lib/app_post/utils.js.coffee

@@ -159,7 +159,7 @@ class App.Utils
     quote = (str) ->
       (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")
 
-    console.log('SC', messageText, signatureText, quote(signatureText))
+    #console.log('SC', messageText, signatureText, quote(signatureText))
     regex = new RegExp( quote(signatureText), 'mi' )
     if messageText.match(regex)
       false
@@ -194,3 +194,58 @@ class App.Utils
   # cleanString = App.Utils.htmlAttributeCleanup( string )
   @htmlAttributeCleanup: (string) ->
     string.replace(/((?![-a-zA-Z0-9_]+).|\n|\r|\t)/gm, '')
+
+  # diff = App.Utils.formDiff( dataNow, dataLast )
+  @formDiff: ( dataNowRaw, dataLastRaw ) ->
+
+    # do type convertation to compare it against form
+    dataNow = clone(dataNowRaw)
+    @_formDiffNormalizer(dataNow)
+    dataLast = clone(dataLastRaw)
+    @_formDiffNormalizer(dataLast)
+
+    @_formDiffChanges( dataNow, dataLast )
+
+  @_formDiffChanges: (dataNow, dataLast, changes = {}) ->
+    for dataNowkey, dataNowValue of dataNow
+      if dataNow[dataNowkey] isnt dataLast[dataNowkey]
+        if _.isArray( dataNow[dataNowkey] ) && _.isArray( dataLast[dataNowkey] )
+          diff = _.difference( dataNow[dataNowkey], dataLast[dataNowkey] )
+          if !_.isEmpty( diff )
+            changes[dataNowkey] = diff
+        else if _.isObject( dataNow[dataNowkey] ) &&  _.isObject( dataLast[dataNowkey] )
+          changes = @_formDiffChanges( dataNow[dataNowkey], dataLast[dataNowkey], changes )
+        else
+          changes[dataNowkey] = dataNow[dataNowkey]
+    changes
+
+  @_formDiffNormalizer: (data) ->
+    if _.isArray( data )
+      for i in [0...data.length]
+        data[i] = @_formDiffNormalizer( data[i] )
+    else if _.isObject( data )
+      for key, value of data
+
+        if _.isArray( data[key] )
+          @_formDiffNormalizer( data[key] )
+        else if _.isObject( data[key] )
+          @_formDiffNormalizer( data[key] )
+        else
+          data[key] = @_formDiffNormalizerItem( key, data[key] )
+    else
+      @_formDiffNormalizerItem( '', data )
+
+
+  @_formDiffNormalizerItem: (key, value) ->
+
+    # handel owner/nobody behavior
+    if key is 'owner_id' && value.toString() is '1'
+      value = ''
+    else if typeof value is 'number'
+      value = value.toString()
+
+    # handle null/undefined behavior - we just handle both as the same
+    else if value is null
+      value = undefined
+
+    value

+ 49 - 5
app/assets/javascripts/application.js

@@ -73,11 +73,55 @@ function difference(object1, object2) {
   return changes;
 }
 
-function clone(object) {
-  if (!object) {
-    return object
-  }
-  return JSON.parse(JSON.stringify(object));
+// taken from http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
+function clone(item) {
+    if (!item) { return item; } // null, undefined values check
+
+    var types = [ Number, String, Boolean ],
+        result;
+
+    // normalizing primitives if someone did new String('aaa'), or new Number('444');
+    types.forEach(function(type) {
+        if (item instanceof type) {
+            result = type( item );
+        }
+    });
+
+    if (typeof result == "undefined") {
+        if (Object.prototype.toString.call( item ) === "[object Array]") {
+            result = [];
+            item.forEach(function(child, index, array) {
+                result[index] = clone( child );
+            });
+        } else if (typeof item == "object") {
+            // testing that this is DOM
+            if (item.nodeType && typeof item.cloneNode == "function") {
+                var result = item.cloneNode( true );
+            } else if (!item.prototype) { // check that this is a literal
+                if (item instanceof Date) {
+                    result = new Date(item);
+                } else {
+                    // it is an object literal
+                    result = {};
+                    for (var i in item) {
+                        result[i] = clone( item[i] );
+                    }
+                }
+            } else {
+                // depending what you would like here,
+                // just keep the reference, or create new object
+                if (false && item.constructor) {
+                    // would not advice to do that, reason? Read below
+                    result = new item.constructor();
+                } else {
+                    result = item;
+                }
+            }
+        } else {
+            result = item;
+        }
+    }
+    return result;
 }
 
 jQuery.event.special.remove = {

+ 57 - 0
public/assets/tests/core.js

@@ -426,6 +426,63 @@ test( "config", function() {
   });
 });
 
+
+// clone
+test( "clone", function() {
+
+  // simple
+  var tests = [
+    {
+      key1: 123,
+      key2: 1234
+    },
+    {
+      key1: 123,
+      key2: '1234'
+    },
+    [1,2,4,5,6],
+    {
+      key1: 123,
+      key2: null,
+    },
+    {
+      key1: 123,
+      key2: undefined,
+    },
+    {
+      key1: 123,
+      key2: undefined,
+      key3: {
+        keya: 'some',
+        keyb: undefined,
+      },
+      key4: ['a', 'b', null, false, true, undefined],
+    },
+    undefined,
+    false,
+    true,
+    null,
+    {
+      key1: 123,
+      key2: undefined,
+      key3: {
+        keya: 'some',
+        keyb: undefined,
+      },
+      key4: ['a', 'b', {
+        a: 123,
+        b: [1,5,7,8,1213,1231321]
+      }],
+    },
+  ];
+
+  _.each(tests, function(test) {
+    var item = clone( test )
+    deepEqual( item, test, 'clone' );
+  });
+
+});
+
 // diff
 test( "diff", function() {
 

+ 2 - 1
public/assets/tests/form-validation.js

@@ -201,7 +201,8 @@ test( "date validation check", function() {
   App.ControllerForm.validate( { errors: errors, form: el } )
 
   equal( el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), true, 'check date1 has-error')
-  equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date1 error message')
+  equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message')
+  //equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date1 error message')
 
   // set new values
   el.find('[name="{date}date1___day"]').val('1')

+ 1 - 1
public/assets/tests/form.js

@@ -501,7 +501,7 @@ test( "form dependend fields check", function() {
     select2: "false",
     selectmulti2: [ "true", "false" ],
     selectmultioption1: "false",
-    datetime1: undefined,
+    datetime1: null,
     datetime2: undefined,
     datetime3: '2015-01-11T12:40:00.000Z',
     datetime4: undefined,

+ 275 - 0
public/assets/tests/html-utils.js

@@ -604,4 +604,279 @@ test( "check attibute validation", function() {
 
 });
 
+// check form diff
+test( "check form diff", function() {
+
+  var dataNow = {
+     owner_id:     1,
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  var dataLast = {
+     owner_id:     '',
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  var diff = {}
+  var result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     owner_id:     '1',
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  dataLast = {
+     owner_id:     '',
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  dataLast = {
+     owner_id:     1,
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     owner_id:     '',
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  dataLast = {
+     pending_date: '2015-01-28T09:39:00Z',
+  }
+  diff = {
+    owner_id: '',
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    owner_id:  '',
+    state_ids: [1,5,6,7],
+  }
+  dataLast = {}
+  diff = {
+    owner_id:  '',
+    state_ids: ['1','5','6','7'],
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    owner_id:  1,
+    state_ids: [1,5,7,6],
+  }
+  dataLast = {
+    owner_id:  '',
+    state_ids: [1,5,6,7],
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     owner_id:  1,
+     state_ids: [1,5,6,7],
+  }
+  dataLast = {
+    state_ids: ['1','5','7'],
+  }
+  diff = {
+    owner_id:  '',
+    state_ids: ['6'],
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     owner_id:  '',
+     state_ids: [1,5,6,7],
+  }
+  dataLast = {
+    owner_id:  1,
+    state_ids: [1,5,6,7],
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+     owner_id:  '',
+     state_ids: [1,5,6,7],
+  }
+  dataLast = {
+    owner_id:  5,
+    state_ids: [1,5,6,7],
+  }
+  diff = {
+    owner_id: ''
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    state_id:     4,
+    pending_time: '2015-01-28T11:34:00Z'
+  }
+  dataLast = {
+    state_id:     5,
+    pending_time: undefined
+  }
+  diff = {
+    state_id:     '4',
+    pending_time: '2015-01-28T11:34:00Z'
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    pending_time: undefined
+  }
+  dataLast = {
+    pending_time: null
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    ticket: {
+      pending_time: undefined,
+    },
+  }
+  dataLast = {
+    ticket: {
+      pending_time: null,
+    },
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: '123',
+    ticket: {
+      pending_time: undefined,
+    },
+  }
+  dataLast = {
+    test: '123',
+    ticket: {
+      pending_time: null,
+    },
+  }
+  diff = {}
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: '123',
+  }
+  dataLast = {}
+  diff = {
+    test: '123',
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: '123',
+  }
+  dataLast = {
+    test: [1,2,3,4]
+  }
+  diff = {
+    test: '123',
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: '123',
+  }
+  dataLast = {
+    test: {
+      1: 1,
+      2: 2,
+    }
+  }
+  diff = {
+    test: '123',
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: [1,2,3,'4']
+  }
+  dataLast = {
+    test: '123',
+  }
+  diff = {
+    test: ['1','2','3','4']
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: {
+      1: 1,
+      2: 2,
+    }
+  }
+  dataLast = {
+    test: '123',
+  }
+  diff = {
+    test: {
+      1: '1',
+      2: '2',
+    }
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+  dataNow = {
+    test: '123',
+    ticket: {
+      pending_time: undefined,
+    },
+  }
+  dataLast = {
+    ticket: {
+      pending_time: null,
+    },
+  }
+  diff = {
+    test: '123',
+  }
+  result = App.Utils.formDiff( dataNow, dataLast )
+  deepEqual( result, diff, 'check form diff' );
+
+
+});
+
 }