diff --git a/etemplate/js/et2_widget_historylog.js b/etemplate/js/et2_widget_historylog.js index bba8fafe49..94ac4da3f0 100644 --- a/etemplate/js/et2_widget_historylog.js +++ b/etemplate/js/et2_widget_historylog.js @@ -285,9 +285,40 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], var field = this.options.value['status-widgets'][key]; var attrs = {'readonly': true, 'id': key}; var options = null; + var widget = null; if(typeof field == 'object') { - attrs['select_options'] = field; + var need_box = false; + for(var j in field) + { + if(et2_registry[field[j]]) + { + need_box = true; + break; + } + } + if(need_box) + { + // Multi-part value needs multiple widgets + widget = et2_createWidget('vbox', attrs, this); + for(var i in field) + { + if(typeof field[i] == 'object') + { + attrs['select_options'] = field[i]; + } + else + { + delete attrs['select_options']; + } + var child = et2_createWidget(typeof field[i] == 'string' ? field[i] : 'select', attrs, widget); + child.transformAttributes(attrs); + } + } + else + { + attrs['select_options'] = field; + } } // Check for options after the type, ex: link-entry:infolog else if (field.indexOf(':') > 0) @@ -296,7 +327,10 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], field = options.shift(); } - var widget = et2_createWidget(typeof field == 'string' ? field : 'select', attrs, this); + if(widget == null) + { + widget = et2_createWidget(typeof field == 'string' ? field : 'select', attrs, this); + } // Parse / set legacy options if(options) @@ -336,10 +370,15 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], widget.transformAttributes(attrs); // Save to use for each row + var nodes = widget._children.length ? [] : jQuery(widget.getDetachedNodes()); + for(var i = 0; i < widget._children.length; i++) + { + nodes.push(jQuery(widget._children[i].getDetachedNodes())); + } this.fields[key] = { attrs: attrs, widget: widget, - nodes: jQuery(widget.getDetachedNodes()) + nodes: nodes }; } // Widget for text diffs @@ -351,18 +390,18 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], }, getDOMNode: function(_sender) { - if (_sender == this) - { - return this.div[0]; - } + if (_sender == this) + { + return this.div[0]; + } - for (var i = 0; i < this.columns.length; i++) - { - if (_sender == this.columns[i].widget) - { - return this.dataview.getHeaderContainerNode(i); - } - } + for (var i = 0; i < this.columns.length; i++) + { + if (_sender == this.columns[i].widget) + { + return this.dataview.getHeaderContainerNode(i); + } + } return null; }, @@ -410,8 +449,15 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], var widget = self.columns[i].widget; if(typeof widget == 'undefined' && typeof self.fields[_data.status] != 'undefined') { - nodes = self.fields[_data.status].nodes.clone(); widget = self.fields[_data.status].widget; + if(!widget._children.length) + { + nodes = self.fields[_data.status].nodes.clone(); + } + for(var j = 0; j < widget._children.length; j++) + { + nodes.push(self.fields[_data.status].nodes[j].clone()); + } } else if (widget) { @@ -461,7 +507,24 @@ var et2_historylog = et2_valueWidget.extend([et2_IDataProvider], // No widget fallback - display actual value nodes = ''+_data[self.columns[i].id] + ''; } - if(widget) widget.setDetachedAttributes(nodes, {value:_data[self.columns[i].id]}); + if(widget) + { + if(widget._children.length) + { + // Multi-part values + var box = $j(widget.getDOMNode()).clone(); + for(var j = 0; j < widget._children.length; j++) + { + widget._children[j].setDetachedAttributes(nodes[j], {value:_data[self.columns[i].id][j]}); + box.append(nodes[j]); + } + nodes = box; + } + else + { + widget.setDetachedAttributes(nodes, {value:_data[self.columns[i].id]}); + } + } $j(this).append(nodes); }); $j(tr).append(row.children()); diff --git a/phpgwapi/inc/class.historylog.inc.php b/phpgwapi/inc/class.historylog.inc.php index a98bcfb6c7..7db61086e0 100644 --- a/phpgwapi/inc/class.historylog.inc.php +++ b/phpgwapi/inc/class.historylog.inc.php @@ -249,6 +249,14 @@ class historylog ) as $row) { $row['user_ts'] = $GLOBALS['egw']->db->from_timestamp($row['history_timestamp']) + 3600 * $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset']; + // Explode multi-part values + foreach(array('history_new_value','history_old_value') as $field) + { + if(strpos($row[$field],bo_tracking::ONE2N_SEPERATOR) !== false) + { + $row[$field] = explode(bo_tracking::ONE2N_SEPERATOR,$row[$field]); + } + } // Get information needed for proper display if($row['history_appname'] == 'filemanager') { diff --git a/phpgwapi/js/egw_action/egw_action_common.js b/phpgwapi/js/egw_action/egw_action_common.js index 8c4b645bf5..26f706e895 100644 --- a/phpgwapi/js/egw_action/egw_action_common.js +++ b/phpgwapi/js/egw_action/egw_action_common.js @@ -512,7 +512,7 @@ function sprintf() { case 'd': a = parseInt(a); break; case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break; case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break; - case 'o': a = a.toString(8); break; + case 'o': a = typeof(a) == 'number' ? a.toString(8):JSON.stringify(a); break; case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break; case 'u': a = Math.abs(a); break; case 'x': a = a.toString(16); break; @@ -525,7 +525,7 @@ function sprintf() { o.push(s + (m[4] ? a + p : p + a)); } else { - throw('Huh ?!'); + throw('Invalid sprintf format "' + arguments[0]+'"'); } f = f.substring(m[0].length); }