details:   https://code.openbravo.com/erp/devel/pi/rev/290c9b12a211
changeset: 21111:290c9b12a211
user:      Augusto Mauch <augusto.mauch <at> openbravo.com>
date:      Wed Sep 11 11:03:58 2013 +0200
summary:   Adaptive Filtering Project

This changeset enables the use of adaptive filtering in Openbravo OBViewGrids. 
The adaptive filtering allows to do client side filtering and sorting of the 
grid records if the dataset is small enough. Not only the filtering and sorting 
is almost immediate, but the server load is reduced severily as the server is 
no longer required to do those tasks.

diffstat:

 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js
                 |    9 +-
 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
            |   53 +++-
 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
        |    4 +
 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js
       |   20 +
 
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/ForeignKeyUIDefinition.java
        |    5 +
 
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/YesNoUIDefinition.java
             |    1 +
 
modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DefaultDataSourceService.java
      |   12 +-
 
modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
 |  124 +++++++++-
 8 files changed, 209 insertions(+), 19 deletions(-)

diffs (truncated from 370 to 300 lines):

diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js
--- 
a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js
  Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js
  Wed Sep 11 11:03:58 2013 +0200
@@ -508,10 +508,17 @@
     var i = 0,
         fld, length;
     if (!keepFilterClause) {
+      // forcing fetch from server in case default filters are removed, in 
other
+      // cases adaptive filtering can be used if possible
+      if (this.data) {
+        this.data.forceRefresh = this.filterClause || this.sqlFilterClause;
+        delete this.data.context.params._where;
+      }
+
       delete this.filterClause;
       delete this.sqlFilterClause;
     }
-    this.forceRefresh = true;
+
     if (this.filterEditor) {
       if (this.filterEditor.getEditForm()) {
         this.filterEditor.getEditForm().clearValues();
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
--- 
a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
     Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
     Wed Sep 11 11:03:58 2013 +0200
@@ -63,6 +63,8 @@
   // prevent this.
   editGrid: true,
 
+  textMatchStyle: 'substring',
+
   // ** {{{ editLinkFieldProperties }}} **
   // The properties of the ListGridField created for the edit links.
   editLinkFieldProperties: {
@@ -196,8 +198,8 @@
     // that the _dummy criteria can mean that new/updated records are not
     // shown in the grid
     neverDropUpdatedRows: true,
-    useClientFiltering: false,
-    useClientSorting: false,
+    useClientFiltering: true,
+    useClientSorting: true,
     fetchDelay: 300,
 
     // overridden to update the context/request properties for the fetch
@@ -279,6 +281,14 @@
         this.localData[dsResponse.totalRows] = null;
       }
       return newData;
+    },
+
+    shouldUseClientFiltering: function () {
+      if (this.forceRefresh) {
+        // forcing fetch from server
+        return false;
+      }
+      return this.Super('shouldUseClientFiltering', arguments);
     }
   },
 
@@ -1835,19 +1845,6 @@
 
       // add a dummy criteria to force a fetch
       criteria.criteria.push(isc.OBRestDataSource.getDummyCriterion());
-    } else if (this.forceRefresh) {
-      // add a dummy criteria to force a fetch
-      criteria.criteria.push(isc.OBRestDataSource.getDummyCriterion());
-      delete this.forceRefresh;
-    } else {
-      // remove the _dummy
-      length = criteria.criteria.length;
-      for (i = 0; i < length; i++) {
-        if (criteria.criteria[i].fieldName === 
isc.OBRestDataSource.DUMMY_CRITERION_NAME) {
-          criteria.criteria.removeAt(i);
-          break;
-        }
-      }
     }
 
     // note pass in criteria otherwise infinite looping!
@@ -1956,6 +1953,15 @@
   },
 
   onFetchData: function (criteria, requestProperties) {
+    if (this.data && this.data.forceRefresh) {
+      // to force fetch from server, remove all cached data
+      delete this.data.forceRefresh;
+      delete this.data.localData;
+      delete this.data.allRows;
+      this.data.totalRows = 0;
+      this.data.cachedRows = 0;
+    }
+
     requestProperties = requestProperties || {};
     requestProperties.params = 
this.getFetchRequestParams(requestProperties.params);
   },
@@ -2642,6 +2648,16 @@
   addToCacheData: function (record, rowNum) {
     // originalData is used when the grid is grouped
     var data = this.originalData || this.data;
+
+    // When a new record is inserted and added to cache, existent cache of
+    // rows received from server is replaced with current localData.
+    // Not doing it causes problems when localData does not match allRows
+    // beacause it has been restricted in client through adaptive filters.
+    data.allRows = data.localData;
+    data.allRowsCriteria = data.criteria || {};
+    data.cachedRows = data.localData.length;
+    data.totalRows = data.localData.length;
+
     data.insertCacheData(record, rowNum);
   },
 
@@ -3147,6 +3163,8 @@
 
     this.recomputeCanvasComponents(rowNum);
 
+    this.body.markForRedraw();
+
     return ret;
   },
 
@@ -3454,6 +3472,11 @@
       
layout.editButton.setErrorState(record[isc.OBViewGrid.ERROR_MESSAGE_PROP]);
       
layout.editButton.setErrorMessage(record[isc.OBViewGrid.ERROR_MESSAGE_PROP]);
       record.editColumnLayout = layout;
+
+      if (this.selection && this.selection.lastSelectionItem && 
this.selection.lastSelectionItem._new) {
+        this.selection.lastSelectionItem.editColumnLayout = layout;
+      }
+
       if (record._new) {
         layout.showSaveCancel();
       } else {
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
--- 
a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
 Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
 Wed Sep 11 11:03:58 2013 +0200
@@ -2414,6 +2414,10 @@
         fld.filterEditorType = type.filterEditorType;
       }
 
+      if (type.sortNormalizer) {
+        fld.sortNormalizer = type.sortNormalizer;
+      }
+
       if (!fld.filterEditorProperties) {
         fld.filterEditorProperties = {};
       }
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js
--- 
a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js
        Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js
        Wed Sep 11 11:03:58 2013 +0200
@@ -1200,4 +1200,24 @@
   }
   return -1;
 
+};
+
+OB.Utilities.yesNoSortNormalizer = function (item, field, context) {
+  var value = item[field];
+  if (value === true) {
+    return 1;
+  } else if (value === false) {
+    return 2;
+  } else {
+    return 3;
+  }
+};
+
+OB.Utilities.enumSortNormalizer = function (item, field, context) {
+  var value = item[field],
+      undef;
+  if (value === null || value === undef) {
+    return '-'; // hack to sort nulls last
+  }
+  return ' ' + value;
 };
\ No newline at end of file
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/ForeignKeyUIDefinition.java
--- 
a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/ForeignKeyUIDefinition.java
 Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/ForeignKeyUIDefinition.java
 Wed Sep 11 11:03:58 2013 +0200
@@ -76,4 +76,9 @@
   protected String getSuperGridFieldName(Field field) {
     return super.getGridFieldName(field);
   }
+
+  @Override
+  public String getTypeProperties() {
+    return "sortNormalizer: function (item, field, context){ return 
OB.Utilities.enumSortNormalizer(item, field, context);},";
+  }
 }
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/YesNoUIDefinition.java
--- 
a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/YesNoUIDefinition.java
      Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/YesNoUIDefinition.java
      Wed Sep 11 11:03:58 2013 +0200
@@ -65,6 +65,7 @@
   @Override
   public String getTypeProperties() {
     return "    valueMap: [null, true, false],"
+        + "sortNormalizer: function (item, field, context){ return 
OB.Utilities.yesNoSortNormalizer(item, field, context);},"
         + "shortDisplayFormatter: function(value, field, component, record) {"
         + "return OB.Utilities.getYesNoDisplayValue(value);" + "},  "
         + "createClassicString: function(value) {return 
OB.Utilities.getClassicValue(value);},"
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DefaultDataSourceService.java
--- 
a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DefaultDataSourceService.java
       Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DefaultDataSourceService.java
       Wed Sep 11 11:03:58 2013 +0200
@@ -277,8 +277,12 @@
     if (entity == null) {
       dsProperties = super.getDataSourceProperties(parameters);
     } else {
-      dsProperties = getInitialProperties(entity,
-          parameters.containsKey(DataSourceConstants.MINIMAL_PROPERTY_OUTPUT));
+      if (false) {
+        dsProperties = getInitialProperties(entity,
+            
parameters.containsKey(DataSourceConstants.MINIMAL_PROPERTY_OUTPUT));
+      } else {
+        dsProperties = getInitialProperties(entity, false);
+      }
     }
 
     // now see if there are additional properties, these are often property 
paths
@@ -312,6 +316,10 @@
       // than the original property
       for (String additionalProp : additionalProps) {
         final Property property = DalUtil.getPropertyFromPath(entity, 
additionalProp);
+        if (property == null) {
+          log4j.warn("Couldn't find propery from additional property: " + 
additionalProp);
+          continue;
+        }
         final DataSourceProperty dsProperty = 
DataSourceProperty.createFromProperty(property);
         dsProperty.setAdditional(true);
         dsProperty.setName(additionalProp.replace(DalUtil.DOT, 
DalUtil.FIELDSEPARATOR));
diff -r a555fcd23cc9 -r 290c9b12a211 
modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
--- 
a/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
  Wed Sep 11 12:18:04 2013 +0200
+++ 
b/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
  Wed Sep 11 11:03:58 2013 +0200
@@ -74,6 +74,25 @@
   }
 });
 
+isc.ResultSet.addProperties({
+  _original_removeCacheData: isc.ResultSet.getPrototype().removeCacheData,
+  removeCacheData: function (updateData) {
+    var filteringOnClient = this.allRows !== null,
+        i, index, ds;
+    this._original_removeCacheData(updateData);
+    if (filteringOnClient) {
+      ds = this.getDataSource();
+      // remove any rows that were present in the cache
+      for (i = 0; i < updateData.length; i++) {
+        index = ds.findByKeys(updateData[i], this.localData);
+        if (index !== -1) {
+          this.localData.removeAt(index);
+        }
+      }
+    }
+  }
+});
+
 
 isc.Canvas.addProperties({
 
@@ -785,4 +804,107 @@
     }
     return this._fieldMatchesFilter(fieldValue, filterValue, 
requestProperties);
   }
-});
\ No newline at end of file
+});
+
+// When filtering strings in backend, spaces are replaced by % in the resultant
+// ilike expression. For example if filter is "jo sm" the query will be 
+// "ilike '%jo%sm%'", so "John Smith" would be found. When filtering in client
+// Smartclient doesn't do this conversion. This code, overwrittes Smartclioent
+// string comparator to work like in backend.
+(function () {
+  var i, containsNoBlanks, originalCondition, stringComparisonNoBlanks, 
operators;
+
+  // Replaces isc.contains in the custom string comparator. Blank spaces are 
not
+  // part of the comparision, but they separate different tokens to be found 
in 
+  // the text. It returns true in case the tested text contains, in order, all 
the
+  // tokens separated by blank spaces. 
+  containsNoBlanks = function (tested, test) {
+    var tokens, token, i, pendingToTest, idx;
+    if (!tested) {
+      return true;
+    }
+
+    tokens = test.split(' ');
+    pendingToTest = tested;
+    for (i = 0; i < tokens.length; i++) {
+      token = tokens[i];
+      idx = pendingToTest.indexOf(token);
+      if (token && idx === -1) {
+        return false;
+      }
+      pendingToTest = pendingToTest.substring(idx + token.length);
+    }
+    return true;
+  };
+
+  // Copied from SmartClient's DataSource.js. The only difference is how 
contains
+  // is computed.

------------------------------------------------------------------------------
How ServiceNow helps IT people transform IT departments:
1. Consolidate legacy IT systems to a single system of record for IT
2. Standardize and globalize service processes across IT
3. Implement zero-touch automation to replace manual, redundant tasks
http://pubads.g.doubleclick.net/gampad/clk?id=51271111&iu=/4140/ostg.clktrk
_______________________________________________
Openbravo-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to