From 973f032feb02c24cf201fdb26ec0ac78b18aaa42 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Fri, 21 Apr 2017 12:05:45 -0400 Subject: [PATCH] LP#1708291: teach egIDL a new fieldmapper object representation This patch teaches egIDL how to represent fieldmapper objects as objects with attributes rather than getter/setters. This allows FM objects to be more easily bound to common to Angular input widgets, avoiding the verbosity of getterSetter ng-options and the fact that some widgets like uib-datepicker-popup don't support getterSetter in the first place. Usage is: hash = obj.toTypedHash() and obj = new egCore.idl.fromTypedHash(hash); Signed-off-by: Galen Charlton Signed-off-by: Kathy Lussier Signed-off-by: Dan Wells --- Open-ILS/web/js/ui/default/staff/services/idl.js | 101 +++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/Open-ILS/web/js/ui/default/staff/services/idl.js b/Open-ILS/web/js/ui/default/staff/services/idl.js index 29b79890fc..629e5958e0 100644 --- a/Open-ILS/web/js/ui/default/staff/services/idl.js +++ b/Open-ILS/web/js/ui/default/staff/services/idl.js @@ -144,6 +144,67 @@ angular.module('egCoreMod') return hash; } + service.toTypedHash = function(obj) { + if (!angular.isObject(obj)) return obj; // arrays are objects + + if (angular.isArray(obj)) { // NOTE: flatten arrays not supported + return obj.map(function(item) {return service.toTypedHash(item)}); + } + + var field_names = obj.classname ? + Object.keys(service.classes[obj.classname].field_map) : + Object.keys(obj); + + var hash = {}; + if (obj.classname) { + angular.extend(hash, { + _classname : obj.classname + }); + } + angular.forEach( + field_names, + function(field) { + + var val = service.toTypedHash( + angular.isFunction(obj[field]) ? + obj[field]() : obj[field] + ); + + if (val !== undefined) { + if (obj.classname) { + switch(service.classes[obj.classname].field_map[field].datatype) { + case 'org_unit' : + // aou fieldmapper objects get used as is because + // that's what egOrgSelector expects + // TODO we should probably make egOrgSelector more flexible + // in what it can bind to + hash[field] = obj[field](); + break; + case 'timestamp': + hash[field] = (val === null) ? val : new Date(val); + break; + case 'bool': + if (val == 't') { + hash[field] = true; + } else if (val == 'f') { + hash[field] = false; + } else { + hash[field] = null; + } + break; + default: + hash[field] = val; + } + } else { + hash[field] = val; + } + } + } + ); + + return hash; + } + // returns a simple string key=value string of an IDL object. service.toString = function(obj) { var s = ''; @@ -173,6 +234,46 @@ angular.module('egCoreMod') return new_obj; } + service.fromTypedHash = function(hash) { + if (!angular.isObject(hash)) return hash; + if (angular.isArray(hash)) { + return hash.map(function(item) {return service.fromTypedHash(item)}); + } + if (!hash._classname) return; + + var new_obj = new service[hash._classname]; + var fields = service.classes[hash._classname].field_map; + angular.forEach(fields, function(field) { + switch(field.datatype) { + case 'org_unit': + if (angular.isFunction(hash[field.name])) { + new_obj[field.name] = hash[field.name]; + } else { + new_obj[field.name](hash[field.name]); + } + break; + case 'timestamp': + if (hash[field.name] instanceof Date) { + new_obj[field.name](hash[field.name].toISOString()); + } + break; + case 'bool': + if (hash[field.name] === true) { + new_obj[field.name]('t'); + } else if (hash[field.name] === false) { + new_obj[field.name]('f'); + } + break; + default: + new_obj[field.name](service.fromTypedHash(hash[field.name])); + } + }); + new_obj.isnew(hash._isnew); + new_obj.ischanged(hash._ischanged); + new_obj.isdeleted(hash._isdeleted); + return new_obj; + } + // Transforms a flattened hash (see toHash() or egGridFlatDataProvider) // to a nested hash. // -- 2.11.0