mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-23 08:23:12 +01:00
Fixed correct expanding of names and implemented the dataProvider class
This commit is contained in:
parent
e151398d94
commit
87c0db7be1
@ -61,14 +61,14 @@ var et2_arrayMgr = Class.extend({
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
getValueForID : function(_id) {
|
/* getValueForID : function(_id) {
|
||||||
if (typeof this.data[_id] != "undefined")
|
if (typeof this.data[_id] != "undefined")
|
||||||
{
|
{
|
||||||
return this.data[_id];
|
return this.data[_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path to this content array manager perspective as an array
|
* Returns the path to this content array manager perspective as an array
|
||||||
@ -306,7 +306,6 @@ var et2_readonlysArrayMgr = et2_arrayMgr.extend({
|
|||||||
// If the attribute is set, return that
|
// If the attribute is set, return that
|
||||||
if (typeof _attr != "undefined" && _attr !== null)
|
if (typeof _attr != "undefined" && _attr !== null)
|
||||||
{
|
{
|
||||||
console.log(_attr, et2_evalBool(_attr));
|
|
||||||
return et2_evalBool(_attr);
|
return et2_evalBool(_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +335,32 @@ function et2_arrayValues(_arr)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent to the PHP array_keys function
|
||||||
|
*/
|
||||||
|
function et2_arrayKeys(_arr)
|
||||||
|
{
|
||||||
|
var result = [];
|
||||||
|
for (var key in _arr)
|
||||||
|
{
|
||||||
|
result.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function et2_arrayIntKeys(_arr)
|
||||||
|
{
|
||||||
|
var result = [];
|
||||||
|
for (var key in _arr)
|
||||||
|
{
|
||||||
|
result.push(parseInt(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent to the PHP substr function, partly take from phpjs, licensed under
|
* Equivalent to the PHP substr function, partly take from phpjs, licensed under
|
||||||
* the GPL.
|
* the GPL.
|
||||||
|
@ -80,7 +80,7 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
|
|||||||
// Check whether an validation error entry exists
|
// Check whether an validation error entry exists
|
||||||
if (this.id)
|
if (this.id)
|
||||||
{
|
{
|
||||||
var val = this.getArrayMgr("validation_errors").getValueForID(this.id);
|
var val = this.getArrayMgr("validation_errors").getEntry(this.id);
|
||||||
if (val)
|
if (val)
|
||||||
{
|
{
|
||||||
_attrs["validation_error"] = val;
|
_attrs["validation_error"] = val;
|
||||||
|
@ -119,4 +119,3 @@ var et2_IDetachedDOM = new Interface({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,12 +343,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var parts = [];
|
var parts = [];
|
||||||
|
var hasString = false;
|
||||||
for (var i = 0; i < _string.length; i++)
|
for (var i = 0; i < _string.length; i++)
|
||||||
{
|
{
|
||||||
var part = _string[i];
|
var part = _string[i];
|
||||||
|
|
||||||
if (typeof part == "string")
|
if (typeof part == "string")
|
||||||
{
|
{
|
||||||
|
hasString = true;
|
||||||
// Escape all "'" and "\" chars and add the string to the parts array
|
// Escape all "'" and "\" chars and add the string to the parts array
|
||||||
parts.push("'" + part.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'");
|
parts.push("'" + part.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'");
|
||||||
}
|
}
|
||||||
@ -358,7 +360,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parts.length == 0)
|
if (!hasString) // Force the result to be of the type string
|
||||||
{
|
{
|
||||||
parts.push('""');
|
parts.push('""');
|
||||||
}
|
}
|
||||||
@ -433,6 +435,7 @@
|
|||||||
test("${row}[title]", "10[title]");
|
test("${row}[title]", "10[title]");
|
||||||
test("{$row_cont[title]}", "Hello World!");
|
test("{$row_cont[title]}", "Hello World!");
|
||||||
test('{$cont["$row"][\'title\']}', "Hello World!");
|
test('{$cont["$row"][\'title\']}', "Hello World!");
|
||||||
|
test("$row_cont[${row}[title]]");
|
||||||
test("\\\\", "\\");
|
test("\\\\", "\\");
|
||||||
test("", "");
|
test("", "");
|
||||||
})();*/
|
})();*/
|
||||||
|
@ -41,7 +41,7 @@ var et2_valueWidget = et2_baseWidget.extend({
|
|||||||
// Set the value for this element
|
// Set the value for this element
|
||||||
var contentMgr = this.getArrayMgr("content");
|
var contentMgr = this.getArrayMgr("content");
|
||||||
if (contentMgr != null) {
|
if (contentMgr != null) {
|
||||||
var val = contentMgr.getValueForID(this.id);
|
var val = contentMgr.getEntry(this.id);
|
||||||
if (val !== null)
|
if (val !== null)
|
||||||
{
|
{
|
||||||
_attrs["value"] = val;
|
_attrs["value"] = val;
|
||||||
|
@ -510,7 +510,12 @@ var et2_widget = Class.extend({
|
|||||||
// Apply the content of the modifications array
|
// Apply the content of the modifications array
|
||||||
if (this.id)
|
if (this.id)
|
||||||
{
|
{
|
||||||
var data = this.getArrayMgr("modifications").getValueForID(this.id);
|
if (typeof this.id != "string")
|
||||||
|
{
|
||||||
|
console.log(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = this.getArrayMgr("modifications").getEntry(this.id);
|
||||||
if (data instanceof Object)
|
if (data instanceof Object)
|
||||||
{
|
{
|
||||||
for (var key in data)
|
for (var key in data)
|
||||||
@ -769,7 +774,7 @@ var et2_widget = Class.extend({
|
|||||||
this._template_application = this.getParent().getTemplateApp();
|
this._template_application = this.getParent().getTemplateApp();
|
||||||
return this._template_application;
|
return this._template_application;
|
||||||
}
|
}
|
||||||
return null;
|
return "phpgwapi";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,3 +33,49 @@ var et2_dataview_IViewRange = new Interface({
|
|||||||
setViewRange: function(_range) {}
|
setViewRange: function(_range) {}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface which objects have to implement, that want to act as low level
|
||||||
|
* datasource.
|
||||||
|
*/
|
||||||
|
var et2_IRowFetcher = new Interface({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param _fetchList is an array consisting of objects whith the entries
|
||||||
|
* "startIdx" and "count"
|
||||||
|
* @param _callback is the callback which is called when the data is ready
|
||||||
|
* (may be immediately or deferred). The callback has the following
|
||||||
|
* signature:
|
||||||
|
* function (_rows)
|
||||||
|
* where _rows is an associative array which contains the data for that row.
|
||||||
|
* @param _context is the context in which the callback should run.
|
||||||
|
*/
|
||||||
|
getRows: function(_fetchList, _callback, _context) {}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface the data provider has to implement
|
||||||
|
*/
|
||||||
|
var et2_IDataProvider = new Interface({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total count of grid elements
|
||||||
|
*/
|
||||||
|
getCount: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the given dataRow for the given index. Calls _dataRow.updateData
|
||||||
|
* as soon as data is available for that row.
|
||||||
|
*/
|
||||||
|
registerDataRow: function(_dataRow, _idx) {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops calling _dataRow.updateData for the dataRow registered for the given
|
||||||
|
* index.
|
||||||
|
*/
|
||||||
|
unregisterDataRow: function(_idx) {}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,49 +13,234 @@
|
|||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
et2_inheritance;
|
et2_core_inheritance;
|
||||||
|
et2_core_common;
|
||||||
et2_dataview_interfaces;
|
et2_dataview_interfaces;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var et2_dataview_dataProvider = Class.extend({
|
var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
|
||||||
|
|
||||||
init: function() {
|
/**
|
||||||
this.updateQueue = 0;
|
* Creates this instance of the data provider.
|
||||||
|
*/
|
||||||
|
init: function(_source, _total) {
|
||||||
|
this._source = _source;
|
||||||
|
this._total = _total;
|
||||||
|
|
||||||
|
this._registeredRows = {};
|
||||||
|
|
||||||
|
this._data = {};
|
||||||
|
this._dataCount = 0;
|
||||||
|
|
||||||
|
this._queue = {};
|
||||||
|
this._queueSize = 0;
|
||||||
|
|
||||||
|
this._stepSize = 25; // Count of elements which is loaded at once
|
||||||
|
this._maxCount = 1000; // Maximum count before the elements are cleaned up
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this._cleanupInterval = window.setInterval(function() {self._cleanup()},
|
||||||
|
10 * 1000);
|
||||||
|
this._queueFlushTimeout = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
// Destroy the cleanup timer callback
|
||||||
|
window.clearInterval(this._cleanupInterval);
|
||||||
|
|
||||||
|
// Destroy the _queueFlushTimeout
|
||||||
|
if (this._queueFlushTimeout !== null)
|
||||||
|
{
|
||||||
|
window.clearTimeout(this._queueFlushTimeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total count
|
||||||
|
*/
|
||||||
getCount: function() {
|
getCount: function() {
|
||||||
return 10000;
|
return this._total;
|
||||||
},
|
},
|
||||||
|
|
||||||
registerDataRow: function(_dataRow, _idx) {
|
registerDataRow: function(_dataRow, _idx) {
|
||||||
/* var row = {
|
// Make sure _idx is a int
|
||||||
"type": "dataRow",
|
_idx = parseInt(_idx);
|
||||||
"data": {
|
|
||||||
"ts_title": "Row " + _idx
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get a random value which is used to simulate network latency and time
|
et2_debug("log", "--> registering row", _idx);
|
||||||
// it needs to load the data.
|
|
||||||
var rnd = Math.round(Math.random() * 1000);
|
|
||||||
|
|
||||||
if (rnd < 200)
|
if (typeof this._registeredRows[_idx] != "undefined")
|
||||||
{
|
{
|
||||||
_dataRow.updateData(row);
|
et2_debug("warn", "Overriding data row for index " + _idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.setTimeout(function() {_dataRow.updateData(row); },
|
// Associate the given data row with that index
|
||||||
Math.round(rnd / 2));*/
|
this._registeredRows[_idx] = _dataRow;
|
||||||
|
|
||||||
|
// Check whether an entry exists in the data array - if yes, call the
|
||||||
// All data rows are updated independently of all others - this allows
|
// request immediately
|
||||||
// user input between generation of the widgets.
|
if (typeof this._data[_idx] != "undefined")
|
||||||
//window.setTimeout(function() {_dataRow.updateData({"readonlys": {"__ALL__": true}});}, 0);
|
{
|
||||||
_dataRow.updateData({"content": {"ts_title": "Idx: " + _idx}});
|
this._callUpdateData(_idx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._queueIndex(_idx);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
unregisterDataRow: function(_dataRow) {
|
unregisterDataRow: function(_idx) {
|
||||||
//
|
// Make sure _idx is a int
|
||||||
|
_idx = parseInt(_idx);
|
||||||
|
|
||||||
|
et2_debug("log", "<-- unregistering row", _idx);
|
||||||
|
|
||||||
|
delete(this._data[_idx]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
|
_queueIndex: function(_idx) {
|
||||||
|
// Mark the index as queued
|
||||||
|
if (typeof this._queue[_idx] == "undefined")
|
||||||
|
{
|
||||||
|
this._queue[_idx] = true;
|
||||||
|
this._queueSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._queueSize > this._stepSize)
|
||||||
|
{
|
||||||
|
this._flushQueue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// (Re)start the queue flush timer
|
||||||
|
var self = this;
|
||||||
|
this._stopFlushTimer();
|
||||||
|
this._queueFlushTimeout = window.setTimeout(function() {
|
||||||
|
self._queueFlushTimeout = null;
|
||||||
|
self._flushQueue();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_flushQueue: function() {
|
||||||
|
// Stop the flush timer if it is still active
|
||||||
|
this._stopFlushTimer();
|
||||||
|
|
||||||
|
// Mark all elements in a radius of this._stepSize / 2
|
||||||
|
var marked = {};
|
||||||
|
var r = Math.floor(this._stepSize / 2);
|
||||||
|
for (var key in this._queue)
|
||||||
|
{
|
||||||
|
key = parseInt(key);
|
||||||
|
|
||||||
|
var b = Math.max(0, key - r);
|
||||||
|
var t = Math.min(key + r, this._total - 1);
|
||||||
|
for (var i = b; i <= t; i ++)
|
||||||
|
{
|
||||||
|
marked[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the queue
|
||||||
|
this._queue = {};
|
||||||
|
this._queueSize = 0;
|
||||||
|
|
||||||
|
// Create a list with start indices and counts
|
||||||
|
var fetchList = [];
|
||||||
|
var entry = null;
|
||||||
|
var last = 0;
|
||||||
|
|
||||||
|
// Get the int keys and sort the array numeric
|
||||||
|
var arr = et2_arrayIntKeys(marked).sort(function(a,b){return a > b ? 1 : (a == b ? 0 : -1)});
|
||||||
|
|
||||||
|
for (var i = 0; i < arr.length; i++)
|
||||||
|
{
|
||||||
|
if (i == 0 || arr[i] - last > 1)
|
||||||
|
{
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
fetchList.push(entry);
|
||||||
|
}
|
||||||
|
entry = {
|
||||||
|
"startIdx": arr[i],
|
||||||
|
"count": 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
fetchList.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the "getRows" callback
|
||||||
|
this._source.getRows(fetchList, this._receiveData, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
_receiveData: function(_data) {
|
||||||
|
var time = (new Date).getTime();
|
||||||
|
|
||||||
|
for (var key in _data)
|
||||||
|
{
|
||||||
|
// Make sure the key is a int
|
||||||
|
key = parseInt(key);
|
||||||
|
|
||||||
|
// Copy the data for the given index
|
||||||
|
this._data[key] = {
|
||||||
|
"data": _data[key],
|
||||||
|
"timestamp": time
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the row associated to the index
|
||||||
|
this._callUpdateData(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_stopFlushTimer: function() {
|
||||||
|
// Stop the queue flush timer
|
||||||
|
if (this._queueFlushTimeout !== null)
|
||||||
|
{
|
||||||
|
window.clearTimeout(this._queueFlushTimeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_callUpdateData: function(_idx) {
|
||||||
|
if (typeof this._registeredRows[_idx] != "undefined")
|
||||||
|
{
|
||||||
|
// this._data[idx].timestamp = (new Date).getTime();
|
||||||
|
this._registeredRows[_idx].updateData({
|
||||||
|
"content": this._data[_idx].data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_cleanup: function() {
|
||||||
|
// Delete all data rows which have not been accessed for more than
|
||||||
|
// "delta" ms (5 minutes) - this method does not ensure that _dataCount
|
||||||
|
// gets below _maxCount!
|
||||||
|
var delta = 5 * 60 * 1000;
|
||||||
|
var now = (new Date).getTime();
|
||||||
|
|
||||||
|
if (this._dataCount > this._maxCount)
|
||||||
|
{
|
||||||
|
for (var key in this._data)
|
||||||
|
{
|
||||||
|
var entry = this._data[key];
|
||||||
|
|
||||||
|
if (now - entry.timestamp > delta)
|
||||||
|
{
|
||||||
|
delete(this._data[key]);
|
||||||
|
this._dataCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -101,6 +101,12 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
|||||||
// Invalidate the parent node
|
// Invalidate the parent node
|
||||||
if (this._parent)
|
if (this._parent)
|
||||||
{
|
{
|
||||||
|
// Invalidate the neighbor node
|
||||||
|
if (this._pidx < this._parent._children.length - 1)
|
||||||
|
{
|
||||||
|
this._parent._children[this._pidx + 1].invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
this._parent.invalidate(origin ? this : _sender);
|
this._parent.invalidate(origin ? this : _sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
|||||||
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
||||||
|
|
||||||
this._avgHeight = _avgHeight;
|
this._avgHeight = _avgHeight;
|
||||||
|
this._idx = null;
|
||||||
|
|
||||||
this.rowWidget = null;
|
this.rowWidget = null;
|
||||||
this.hasAvgHeight = false;
|
this.hasAvgHeight = false;
|
||||||
@ -37,7 +38,10 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
|||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
|
||||||
// Unregister the row from the data provider
|
// Unregister the row from the data provider
|
||||||
this.dataProvider.unregisterDataRow(this);
|
if (this._idx !== null)
|
||||||
|
{
|
||||||
|
this.dataProvider.unregisterDataRow(this._idx);
|
||||||
|
}
|
||||||
|
|
||||||
// Free the row widget first, if it has been set
|
// Free the row widget first, if it has been set
|
||||||
if (this.rowWidget)
|
if (this.rowWidget)
|
||||||
|
@ -76,17 +76,6 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
"data": []
|
"data": []
|
||||||
};
|
};
|
||||||
|
|
||||||
// Include the "value" attribute if the widget is derrived from
|
|
||||||
// et2_valueWidget
|
|
||||||
if (_widget instanceof et2_valueWidget)
|
|
||||||
{
|
|
||||||
hasAttr = true;
|
|
||||||
widgetData.data.push({
|
|
||||||
"attribute": "value",
|
|
||||||
"expression": "@${row}"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all attribute values
|
// Get all attribute values
|
||||||
for (var key in _widget.attributes)
|
for (var key in _widget.attributes)
|
||||||
{
|
{
|
||||||
@ -166,13 +155,22 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
// "detached" mode
|
// "detached" mode
|
||||||
var supportedAttrs = [];
|
var supportedAttrs = [];
|
||||||
widget.getDetachedAttributes(supportedAttrs);
|
widget.getDetachedAttributes(supportedAttrs);
|
||||||
|
supportedAttrs.push("id");
|
||||||
isDetachable = true;
|
isDetachable = true;
|
||||||
|
|
||||||
for (var j = 0; j < _varAttrs[i].data.length && isDetachable; j++)
|
for (var j = 0; j < _varAttrs[i].data.length/* && isDetachable*/; j++)
|
||||||
{
|
{
|
||||||
var data = _varAttrs[i].data[j];
|
var data = _varAttrs[i].data[j];
|
||||||
|
|
||||||
isDetachable &= supportedAttrs.indexOf(data.attribute) != -1;
|
var supportsAttr = supportedAttrs.indexOf(data.attribute) != -1;
|
||||||
|
|
||||||
|
if (!supportsAttr)
|
||||||
|
{
|
||||||
|
et2_debug("warn", "et2_IDetachedDOM widget " +
|
||||||
|
widget._type + " does not support " + data.attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDetachable &= supportsAttr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +292,7 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
// Record the path to each DOM-Node
|
// Record the path to each DOM-Node
|
||||||
for (var j = 0; j < nodes.length; j++)
|
for (var j = 0; j < nodes.length; j++)
|
||||||
{
|
{
|
||||||
nodeFuncs[i] = this._compileDOMAccessFunc(_rowTemplate.row,
|
nodeFuncs[j] = this._compileDOMAccessFunc(_rowTemplate.row,
|
||||||
nodes[j]);
|
nodes[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +318,7 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create the row widget and insert the given widgets into the row
|
// Create the row widget and insert the given widgets into the row
|
||||||
var rowWidget = new et2_dataview_rowWidget(row[0]);
|
var rowWidget = new et2_dataview_rowWidget(_rootWidget, row[0]);
|
||||||
rowWidget.createWidgets(_widgets);
|
rowWidget.createWidgets(_widgets);
|
||||||
|
|
||||||
// Get the set containing all variable attributes
|
// Get the set containing all variable attributes
|
||||||
@ -354,6 +352,18 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
var rowWidget = null;
|
var rowWidget = null;
|
||||||
if (this._template.seperated.remaining.length > 0)
|
if (this._template.seperated.remaining.length > 0)
|
||||||
{
|
{
|
||||||
|
// Transform the variable attributes
|
||||||
|
for (var i = 0; i < this._template.seperated.remaining.length; i++)
|
||||||
|
{
|
||||||
|
var entry = this._template.seperated.remaining[i];
|
||||||
|
|
||||||
|
for (var j = 0; j < entry.data.length; j++)
|
||||||
|
{
|
||||||
|
var set = entry.data[j];
|
||||||
|
entry.widget.options[set.attribute] = mgrs["content"].expandName(set.expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the row widget
|
// Create the row widget
|
||||||
var rowWidget = new et2_dataview_rowTemplateWidget(this._rootWidget,
|
var rowWidget = new et2_dataview_rowTemplateWidget(this._rootWidget,
|
||||||
_row[0]);
|
_row[0]);
|
||||||
@ -371,7 +381,7 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
var data = {};
|
var data = {};
|
||||||
for (var j = 0; j < entry.data.length; j++)
|
for (var j = 0; j < entry.data.length; j++)
|
||||||
{
|
{
|
||||||
var set = entry.data[i];
|
var set = entry.data[j];
|
||||||
data[set.attribute] = mgrs["content"].expandName(set.expression);
|
data[set.attribute] = mgrs["content"].expandName(set.expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,6 +394,13 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
nodes[j] = entry.nodeFuncs[j](_row[0]);
|
nodes[j] = entry.nodeFuncs[j](_row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the array managers first
|
||||||
|
entry.widget._mgrs = mgrs;
|
||||||
|
if (typeof data.id != "undefined")
|
||||||
|
{
|
||||||
|
entry.widget.id = data.id;
|
||||||
|
}
|
||||||
|
|
||||||
// Call the setDetachedAttributes function
|
// Call the setDetachedAttributes function
|
||||||
entry.widget.setDetachedAttributes(nodes, data);
|
entry.widget.setDetachedAttributes(nodes, data);
|
||||||
}
|
}
|
||||||
@ -431,9 +448,9 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
|
|
||||||
var et2_dataview_rowWidget = et2_widget.extend(et2_IDOMNode, {
|
var et2_dataview_rowWidget = et2_widget.extend(et2_IDOMNode, {
|
||||||
|
|
||||||
init: function(_row) {
|
init: function(_parent, _row) {
|
||||||
// Call the parent constructor with some dummy attributes
|
// Call the parent constructor with some dummy attributes
|
||||||
this._super(null, {"id": "", "type": "rowWidget"});
|
this._super(_parent, {"id": "", "type": "rowWidget"});
|
||||||
|
|
||||||
// Initialize some variables
|
// Initialize some variables
|
||||||
this._widgets = [];
|
this._widgets = [];
|
||||||
|
@ -71,7 +71,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|||||||
|
|
||||||
// Create the data provider which cares about streaming the row data
|
// Create the data provider which cares about streaming the row data
|
||||||
// efficiently to the rows
|
// efficiently to the rows
|
||||||
this.dataProvider = new et2_dataview_dataProvider();
|
this.dataProvider = new et2_dataview_dataProvider(this, 100);
|
||||||
|
|
||||||
// Create the outer grid container
|
// Create the outer grid container
|
||||||
this.dataviewContainer = new et2_dataview_gridContainer(this.div,
|
this.dataviewContainer = new et2_dataview_gridContainer(this.div,
|
||||||
@ -101,6 +101,26 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Rows callback
|
||||||
|
*/
|
||||||
|
getRows: function(_fetchList, _callback, _context) {
|
||||||
|
console.log("Nextmatch will fetch ", _fetchList);
|
||||||
|
// Create the entries:
|
||||||
|
var entries = {};
|
||||||
|
for (var i = 0; i < _fetchList.length; i++)
|
||||||
|
{
|
||||||
|
var start = _fetchList[i].startIdx;
|
||||||
|
for (var j = 0; j < _fetchList[i].count; j++)
|
||||||
|
{
|
||||||
|
entries[start + j] =
|
||||||
|
{"info_id":"5","info_type":"email","info_from":"tracker","info_addr":"tracker","info_subject":"InfoLog grid view: problem with Opera; 'permission denied' while saving","info_des":"<snip>","info_owner":"5","info_responsible":[],"info_access":"public","info_cat":"0","info_datemodified":1307112528,"info_startdate":1306503000,"info_enddate":"0", "info_id_parent":"0","info_planned_time":"0","info_replanned_time":"0","info_used_time":"0","info_status":"done", "info_confirm":"not","info_modifier":"5","info_link_id":0,"info_priority":"1","pl_id":"0","info_price":null, "info_percent":"100%","info_datecompleted":1307112528,"info_location":"","info_custom_from":1, "info_uid":"infolog-5-18d12c7bf195f6b9d602e1fa5cde28f1","info_cc":"","caldav_name":"5.ics","info_etag":"0", "info_created":1307112528,"info_creator":"5","links":[],"info_anz_subs":0,"sub_class":"normal_done","info_link":{"title":"tracker"},"class":"rowNoClose rowNoCloseAll ","info_type_label":"E-Mail","info_status_label":"done","info_number":"5"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_callback.call(_context, entries);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the nextmatch widget by the given ID.
|
* Sorts the nextmatch widget by the given ID.
|
||||||
*
|
*
|
||||||
@ -253,7 +273,6 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|||||||
/**
|
/**
|
||||||
* When the template attribute is set, the nextmatch widget tries to load
|
* When the template attribute is set, the nextmatch widget tries to load
|
||||||
* that template and to fetch the grid which is inside of it. It then calls
|
* that template and to fetch the grid which is inside of it. It then calls
|
||||||
* _parseGrid in order to get the information for the column headers etc.
|
|
||||||
*/
|
*/
|
||||||
set_template: function(_value) {
|
set_template: function(_value) {
|
||||||
if (!this.template)
|
if (!this.template)
|
||||||
|
@ -81,9 +81,6 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
|||||||
init: function() {
|
init: function() {
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
this.value = "";
|
|
||||||
this.font_style = "";
|
|
||||||
|
|
||||||
// Create the span/label tag which contains the label text
|
// Create the span/label tag which contains the label text
|
||||||
this.span = $j(document.createElement(this.options["for"] ? "label" : "span"))
|
this.span = $j(document.createElement(this.options["for"] ? "label" : "span"))
|
||||||
.addClass("et2_label");
|
.addClass("et2_label");
|
||||||
@ -100,6 +97,20 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
|||||||
this.setDOMNode(this.span[0]);
|
this.setDOMNode(this.span[0]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
transformAttributes: function(_attrs) {
|
||||||
|
this._super.apply(arguments);
|
||||||
|
|
||||||
|
if (this.id)
|
||||||
|
{
|
||||||
|
var val = this.getArrayMgr("content").getEntry(this.id);
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
_attrs["value"] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_parseText: function(_value) {
|
_parseText: function(_value) {
|
||||||
if (this.options.href)
|
if (this.options.href)
|
||||||
{
|
{
|
||||||
@ -131,7 +142,7 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
|||||||
|
|
||||||
getDetachedAttributes: function(_attrs)
|
getDetachedAttributes: function(_attrs)
|
||||||
{
|
{
|
||||||
_attrs.push("value");
|
_attrs.push("value", "class");
|
||||||
},
|
},
|
||||||
|
|
||||||
getDetachedNodes: function()
|
getDetachedNodes: function()
|
||||||
@ -141,11 +152,18 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
|||||||
|
|
||||||
setDetachedAttributes: function(_nodes, _values)
|
setDetachedAttributes: function(_nodes, _values)
|
||||||
{
|
{
|
||||||
|
this.transformAttributes(_values);
|
||||||
|
|
||||||
if (typeof _values["value"] != "undefined")
|
if (typeof _values["value"] != "undefined")
|
||||||
{
|
{
|
||||||
et2_insertLinkText(this._parseText(_values["value"]), _nodes[0],
|
et2_insertLinkText(this._parseText(_values["value"]), _nodes[0],
|
||||||
this.options.extra_link_target);
|
this.options.extra_link_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof _values["class"] != "undefined")
|
||||||
|
{
|
||||||
|
this.set_class(_values["class"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,13 +14,14 @@
|
|||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
|
et2_core_interfaces;
|
||||||
et2_core_baseWidget;
|
et2_core_baseWidget;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which implements the "image" XET-Tag
|
* Class which implements the "image" XET-Tag
|
||||||
*/
|
*/
|
||||||
var et2_image = et2_baseWidget.extend({
|
var et2_image = et2_baseWidget.extend(/*et2_IDetachedDOM,*/ {
|
||||||
|
|
||||||
attributes: {
|
attributes: {
|
||||||
"src": {
|
"src": {
|
||||||
@ -44,17 +45,31 @@ var et2_image = et2_baseWidget.extend({
|
|||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
// Create the image or a/image tag
|
// Create the image or a/image tag
|
||||||
this.image = this.node = $j(document.createElement("img"));
|
var node = this.image = $j(document.createElement("img"));
|
||||||
if(this.options.link)
|
if(this.options.link)
|
||||||
{
|
{
|
||||||
this.node = $j(document.createElement("a"));
|
this._node = $j(document.createElement("a"));
|
||||||
this.image.appendTo(this.node);
|
this.image.appendTo(node);
|
||||||
}
|
}
|
||||||
if(this.options["class"])
|
if(this.options["class"])
|
||||||
{
|
{
|
||||||
this.node.addClass(this.options["class"]);
|
node.addClass(this.options["class"]);
|
||||||
|
}
|
||||||
|
this.setDOMNode(node[0]);
|
||||||
|
},
|
||||||
|
|
||||||
|
transformAttributes: function(_attrs) {
|
||||||
|
this._super.apply(arguments);
|
||||||
|
|
||||||
|
// Check to expand name
|
||||||
|
if (typeof _attrs["src"] != "undefined")
|
||||||
|
{
|
||||||
|
var src = this.getArrayMgr("content").getEntry(_attrs["src"]);
|
||||||
|
if (src)
|
||||||
|
{
|
||||||
|
_attrs["src"] = src;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.setDOMNode(this.node[0]);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set_label: function(_value) {
|
set_label: function(_value) {
|
||||||
@ -62,7 +77,7 @@ var et2_image = et2_baseWidget.extend({
|
|||||||
this.options.label = _value;
|
this.options.label = _value;
|
||||||
// label is NOT the alt attribute in eTemplate, but the title/tooltip
|
// label is NOT the alt attribute in eTemplate, but the title/tooltip
|
||||||
this.image.attr("alt", _value);
|
this.image.attr("alt", _value);
|
||||||
this.image.set_statustext(_value);
|
this.set_statustext(_value);
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue: function(_value) {
|
setValue: function(_value) {
|
||||||
@ -70,27 +85,25 @@ var et2_image = et2_baseWidget.extend({
|
|||||||
this.set_src(_value);
|
this.set_src(_value);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
percentagePreg: /^[0-9]+%$/,
|
||||||
|
|
||||||
set_src: function(_value) {
|
set_src: function(_value) {
|
||||||
if(!this.isInTree())
|
if(!this.isInTree())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to expand name
|
|
||||||
if(_value.indexOf("$") != -1 || _value.indexOf("@") != -1) {
|
|
||||||
var contentMgr = this.getArrayMgr("content");
|
|
||||||
if (contentMgr != null) {
|
|
||||||
var val = contentMgr.getValueForID(_value);
|
|
||||||
if (val !== null)
|
|
||||||
{
|
|
||||||
_value = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.options.src = _value;
|
this.options.src = _value;
|
||||||
|
|
||||||
|
// Check whether "src" is a percentage
|
||||||
|
if (this.percentagePreg.test(_value))
|
||||||
|
{
|
||||||
|
this.getSurroundings().prependDOMNode(document.createTextNode(_value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Get application to use from template ID
|
// Get application to use from template ID
|
||||||
var appname = this.getTemplateApp();
|
var src = egw.image(_value, this.getTemplateApp());
|
||||||
var src = egw.image(_value,appname || "phpgwapi");
|
|
||||||
if(src)
|
if(src)
|
||||||
{
|
{
|
||||||
this.image.attr("src", src).show();
|
this.image.attr("src", src).show();
|
||||||
@ -100,6 +113,41 @@ var et2_image = et2_baseWidget.extend({
|
|||||||
this.image.css("display","none");
|
this.image.css("display","none");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of "et2_IDetachedDOM" for fast viewing in gridview
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Does currently not work for percentages, as the surroundings manager
|
||||||
|
// cannot opperate on other DOM-Nodes.
|
||||||
|
|
||||||
|
/* getDetachedAttributes: function(_attrs) {
|
||||||
|
_attrs.push("src", "label");
|
||||||
|
},
|
||||||
|
|
||||||
|
getDetachedNodes: function() {
|
||||||
|
return [this.node, this.image[0]];
|
||||||
|
},
|
||||||
|
|
||||||
|
setDetachedAttributes: function(_nodes, _values) {
|
||||||
|
// Set the given DOM-Nodes
|
||||||
|
this.node = _nodes[0];
|
||||||
|
this.image = $j(_nodes[1]);
|
||||||
|
|
||||||
|
this.transformAttributes(_values);
|
||||||
|
|
||||||
|
// Set the attributes
|
||||||
|
if (_values["src"])
|
||||||
|
{
|
||||||
|
this.set_src(_values["src"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_values["label"])
|
||||||
|
{
|
||||||
|
this.set_label(_values["label"]);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
});
|
});
|
||||||
|
|
||||||
et2_register_widget(et2_image, ["image"]);
|
et2_register_widget(et2_image, ["image"]);
|
||||||
|
@ -118,7 +118,7 @@ var et2_link_to = et2_inputWidget.extend({
|
|||||||
if (_attrs["select_options"] == null)
|
if (_attrs["select_options"] == null)
|
||||||
{
|
{
|
||||||
_attrs["select_options"] = this.getArrayMgr('content')
|
_attrs["select_options"] = this.getArrayMgr('content')
|
||||||
.getValueForID("options-" + this.id)
|
.getEntry("options-" + this.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to an empty object
|
// Default to an empty object
|
||||||
|
@ -77,14 +77,14 @@ var et2_selectbox = et2_inputWidget.extend({
|
|||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
// Try to find the options inside the "sel-options" array
|
// Try to find the options inside the "sel-options" array
|
||||||
_attrs["select_options"] = this.getArrayMgr("sel_options").getValueForID(this.id);
|
_attrs["select_options"] = this.getArrayMgr("sel_options").getEntry(this.id);
|
||||||
|
|
||||||
// Check whether the options entry was found, if not read it from the
|
// Check whether the options entry was found, if not read it from the
|
||||||
// content array.
|
// content array.
|
||||||
if (_attrs["select_options"] == null)
|
if (_attrs["select_options"] == null)
|
||||||
{
|
{
|
||||||
_attrs["select_options"] = this.getArrayMgr('content')
|
_attrs["select_options"] = this.getArrayMgr('content')
|
||||||
.getValueForID("options-" + this.id)
|
.getEntry("options-" + this.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to an empty object
|
// Default to an empty object
|
||||||
|
@ -64,7 +64,7 @@ var et2_tabbox = et2_DOMWidget.extend({
|
|||||||
// Set the value for this element
|
// Set the value for this element
|
||||||
var contentMgr = this.getArrayMgr("content");
|
var contentMgr = this.getArrayMgr("content");
|
||||||
if (contentMgr != null) {
|
if (contentMgr != null) {
|
||||||
var val = contentMgr.getValueForID(this.id);
|
var val = contentMgr.getEntry(this.id);
|
||||||
if (val !== null)
|
if (val !== null)
|
||||||
{
|
{
|
||||||
selected = val;
|
selected = val;
|
||||||
@ -72,7 +72,7 @@ var et2_tabbox = et2_DOMWidget.extend({
|
|||||||
}
|
}
|
||||||
contentMgr = this.getArrayMgr("readonlys");
|
contentMgr = this.getArrayMgr("readonlys");
|
||||||
if (contentMgr != null) {
|
if (contentMgr != null) {
|
||||||
var val = contentMgr.getValueForID(this.id);
|
var val = contentMgr.getEntry(this.id);
|
||||||
if (val !== null)
|
if (val !== null)
|
||||||
{
|
{
|
||||||
hidden = val;
|
hidden = val;
|
||||||
|
@ -63,19 +63,69 @@
|
|||||||
<nextmatch-sortheader label="last changed" id="info_datemodified" options="DESC"/>
|
<nextmatch-sortheader label="last changed" id="info_datemodified" options="DESC"/>
|
||||||
</row>
|
</row>
|
||||||
<row class="$row_cont[info_cat] $row_cont[class]" valign="top">
|
<row class="$row_cont[info_cat] $row_cont[class]" valign="top">
|
||||||
<vbox>
|
<hbox align="center" options="5">
|
||||||
<description value="Dynamic description tag:" />
|
<image label="$row_cont[info_type]" src="${row}[info_type]"/>
|
||||||
<description value="$cont[$row][ts_title]" />
|
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_status_label]" id="edit_status[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_status_label]" ro_image="$row_cont[info_status_label]"/>
|
||||||
<button label="This is a button" />
|
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_percent]" id="edit_percent[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_percent]"/>
|
||||||
|
<image label="$row_cont[info_percent2]" src="{$row}[info_percent2]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;"/>
|
||||||
|
</hbox>
|
||||||
|
<vbox options="0,0" class="fullWidth">
|
||||||
|
<link label="%s $row_cont[info_addr]" id="${row}[info_link]" options="b"/>
|
||||||
|
<hbox options="0,0">
|
||||||
|
<description id="${row}[info_subject]" no_lang="1" class="$row_cont[sub_class]"/>
|
||||||
|
<description align="right" id="{$row}[info_number]" no_lang="1" class="infoId"/>
|
||||||
|
</hbox>
|
||||||
|
<box class="infoDes">
|
||||||
|
<description id="${row}[info_des]" no_lang="1" options=",,1"/>
|
||||||
|
</box>
|
||||||
|
<link-string id="${row}[filelinks]"/>
|
||||||
|
</vbox>
|
||||||
|
<customfields-list id="$row" class="customfields"/>
|
||||||
|
<menulist>
|
||||||
|
<menupopup type="select-cat" id="${row}[info_cat]" readonly="true"/>
|
||||||
|
</menulist>
|
||||||
|
<vbox cols="1" rows="3" options="0,0,1">
|
||||||
|
<date-time id="${row}[info_startdate]" readonly="true" options=",8" class="fixedHeight"/>
|
||||||
|
<date id="${row}[info_enddate]" readonly="true" class="$row_cont[end_class] fixedHeight"/>
|
||||||
|
<date-time id="${row}[info_datecompleted]" readonly="true" class="fixedHeight"/>
|
||||||
|
</vbox>
|
||||||
|
<vbox cols="1" rows="3" options="0,0">
|
||||||
|
<hbox readonly="true">
|
||||||
|
<hbox readonly="true" options="1,0">
|
||||||
|
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
|
||||||
|
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
|
||||||
|
</hbox>
|
||||||
|
<description/>
|
||||||
|
</hbox>
|
||||||
|
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
|
||||||
|
</vbox>
|
||||||
|
<vbox cols="1" rows="3" options="0,0">
|
||||||
|
<hbox id="r_used_time" options="1,0">
|
||||||
|
<image label="Times" src="timesheet"/>
|
||||||
|
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
|
||||||
|
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
|
||||||
|
</hbox>
|
||||||
|
<hbox id="planified" options="1,0">
|
||||||
|
<image label="planned time" src="k_alarm.png"/>
|
||||||
|
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
|
||||||
|
</hbox>
|
||||||
|
<hbox id="replanified" options="1,0">
|
||||||
|
<image label="Re-planned time" src="agt_reload.png"/>
|
||||||
|
<date-duration id="${row}[info_replanned_time]" readonly="true" options="@duration_format" span="all" class="replanned"/>
|
||||||
|
</hbox>
|
||||||
|
</vbox>
|
||||||
|
<vbox options="0,0">
|
||||||
|
<menulist>
|
||||||
|
<menupopup type="select-account" id="${row}[info_owner]" readonly="true"/>
|
||||||
|
</menulist>
|
||||||
|
<listbox type="select-account" id="${row}[info_responsible]" readonly="true" rows="5"/>
|
||||||
|
</vbox>
|
||||||
|
<vbox options="0" orient="0">
|
||||||
|
<date-time id="${row}[info_datemodified]" readonly="true"/>
|
||||||
|
<menulist>
|
||||||
|
<menupopup type="select-account" id="${row}[info_modifier]" readonly="true"/>
|
||||||
|
</menulist>
|
||||||
</vbox>
|
</vbox>
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test" />
|
|
||||||
<description value="test2" />
|
|
||||||
</row>
|
</row>
|
||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
|
Loading…
Reference in New Issue
Block a user