Loading data from server in nextmatch widget - readonlys is not processed as it is not so easy to handle

This commit is contained in:
Andreas Stöckel 2011-09-09 14:32:55 +00:00
parent 50ad9e4ba0
commit 2290b04102
7 changed files with 211 additions and 32 deletions

View File

@ -68,7 +68,12 @@ class etemplate_widget_nextmatch extends etemplate_widget
{
public function __construct($xml='')
{
if($xml) parent::__construct($xml);
if($xml) {
parent::__construct($xml);
// TODO: probably a better way to do this
egw_framework::includeCSS('/phpgwapi/js/egw_action/test/skins/dhtmlxmenu_egw.css');
}
}
/**
@ -108,7 +113,7 @@ class etemplate_widget_nextmatch extends etemplate_widget
*/
static public function ajax_get_rows($exec_id, $fetchList, $form_name='nm')
{
error_log(__METHOD__."(".array2string($fetchList).")");
error_log(__METHOD__."($exec_id,".array2string($fetchList).",$form_name)");
// Force the array to be associative
self::$request = etemplate_request::read($exec_id);
@ -128,16 +133,7 @@ class etemplate_widget_nextmatch extends etemplate_widget
$result['rows'][$entry['startIdx']+$n] = $row;
}
}
/*
$result = array("null" => null);
foreach ($fetchList as $entry)
{
for ($i = 0; $i < $entry["count"]; $i++)
{
$result[$entry["startIdx"] + $i] = json_decode('{"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"}');
}
}
*/
$response = egw_json_response::get();
$response->data($result);
}

View File

@ -74,7 +74,12 @@ var et2_IDataProvider = new Interface({
* Stops calling _dataRow.updateData for the dataRow registered for the given
* index.
*/
unregisterDataRow: function(_idx) {}
unregisterDataRow: function(_idx) {},
/**
* Returns the action object manager (if one exists, otherwise null)
*/
getActionObjectManager: function() {}
});

View File

@ -13,6 +13,8 @@
"use strict"
/*egw:uses
egw_action.egw_action;
et2_core_inheritance;
et2_core_common;
et2_dataview_interfaces;
@ -23,7 +25,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
/**
* Creates this instance of the data provider.
*/
init: function(_source, _total) {
init: function(_source, _total, _actionMgr) {
this._source = _source;
this._total = _total;
@ -38,6 +40,9 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
this._stepSize = 25; // Count of elements which is loaded at once
this._maxCount = 1000; // Maximum count before the elements are cleaned up
// Create an action object manager
this.actionObjectManager = new egwActionObjectManager("", _actionMgr);
var self = this;
this._cleanupInterval = window.setInterval(function() {self._cleanup()},
10 * 1000);
@ -49,10 +54,33 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
window.clearInterval(this._cleanupInterval);
// Destroy the _queueFlushTimeout
if (this._queueFlushTimeout !== null)
{
window.clearTimeout(this._queueFlushTimeout);
}
this._stopFlushTimer();
// Destroy the actionObject manager
this.actionObjectManager.clear();
},
/**
* Resets the stored data and aborts any queue request
*/
clear: function() {
this._data = {};
this._dataCount = 0;
this._queue = {};
this._queueSize = 0;
this._stopFlushTimer();
// Clear all elements in the action object manager
this.actionObjectManager.clear();
},
/**
* Data is an object containing an "rows" and "readonlys" array.
*/
loadData: function(_data) {
this._receiveData(_data);
},
/**
@ -93,6 +121,10 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
delete(this._registeredRows[_idx]);
},
getActionObjectManager: function() {
return this.actionObjectManager;
},
/* ---- PRIVATE FUNCTIONS ---- */
_queueIndex: function(_idx) {
@ -188,7 +220,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
_receiveData: function(_data) {
var time = (new Date).getTime();
for (var key in _data)
for (var key in _data.rows)
{
if (!isNaN(key))
{
@ -197,7 +229,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
// Copy the data for the given index
this._data[key] = {
"data": _data[key],
"data": _data.rows[key],
"timestamp": time
};
@ -218,7 +250,6 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
_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
});

View File

@ -91,7 +91,7 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
// Create the partition tree object which is used to organize the tree
// items.
partitionTree = this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
this._rowProvider, this._avgHeight, this.innerTbody);
// Setup the "rebuild" timer - it rebuilds the complete partition tree
@ -117,6 +117,16 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
this._partitionTree.free();
},
clear: function() {
// Free the partition tree and recreate it
this._partitionTree.free();
this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
this._rowProvider, this._avgHeight, this.innerTbody);
// Set the viewrange again
this.setViewRange(this._currentRange);
},
/**
* The setViewRange function updates the range in which columns are shown.
*/
@ -137,8 +147,6 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
}
}
// Deactivated the code below for testing purposes
// Calculate the range of the actually shown elements
var displayTop = _range.top;
var displayBottom = _range.bottom;

View File

@ -91,6 +91,16 @@ var et2_dataview_gridContainer = Class.extend({
this.table.remove();
},
/**
* Clears all data rows and reloads them
*/
clear: function() {
if (this.grid)
{
this.grid.clear();
}
},
/**
* Returns the column container node for the given column index
*

View File

@ -13,8 +13,11 @@
"use strict";
/*egw:uses
egw_action.egw_action;
et2_dataview_interfaces;
et2_dataview_view_container;
et2_dataview_view_rowAOI;
*/
var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
@ -27,6 +30,7 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
this._idx = null;
this.rowWidget = null;
this.actionObject = null;
this.hasAvgHeight = false;
// Get the default row object and scale the row to the average height
@ -50,6 +54,13 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
this.rowWidget.free();
}
// Free the action object and remove it from the action object manager
if (this.actionObject)
{
// Delete the action object from the surrounding manager
this.actionObject.remove();
}
this._super();
},
@ -69,6 +80,23 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
},
updateData: function(_data) {
// Free all old data in the action object
if (this.actionObject)
{
this.actionObject.clear();
}
// Create an action object interface for the row
var aom = this.dataProvider.getActionObjectManager();
if (aom)
{
this.actionObject = aom.addObject("row" + this._idx,
new et2_dataview_rowAOI(this.tr[0]));
// TODO: The action links should be inside the data and not inside
// the row classes...
this.actionObject.updateActionLinks(["view","edit"]);
}
// Reset the height
if (this.hasAvgHeight)

View File

@ -13,18 +13,33 @@
"use strict";
/*egw:uses
// Force some base libraries to be loaded
jquery.jquery;
/phpgwapi/egw_json.js;
et2_widget;
// Include the action system
egw_action.egw_action;
egw_action.egw_action_popup;
egw_action.egw_menu_dhtmlx;
// Include some core classes
et2_core_widget;
et2_core_interfaces;
et2_core_DOMWidget;
// Include all widgets the nextmatch extension will create
et2_widget_template;
et2_widget_grid;
et2_widget_selectbox;
// Include the dynheight manager
et2_extension_nextmatch_dynheight;
// Include the grid classes
et2_dataview_view_gridContainer;
et2_dataview_model_dataProvider;
et2_dataview_model_columns;
*/
/**
@ -56,6 +71,11 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
"name": "Template",
"type": "string",
"description": "The id of the template which contains the grid layout."
},
"settings": {
"name": "Settings",
"type": "any",
"description": "The nextmatch settings"
}
},
@ -71,9 +91,21 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
// container.
this.dynheight = new et2_dynheight(null, this.div, 150);
// Create the action manager
this.actionManager = new egwActionManager();
// Create the data provider which cares about streaming the row data
// efficiently to the rows
this.dataProvider = new et2_dataview_dataProvider(this, 100);
// efficiently to the rows.
var total = typeof this.options.settings.total != "undefined" ?
this.options.settings.total : 0;
this.dataProvider = new et2_dataview_dataProvider(this, total,
this.actionManager);
// Load the first data into the dataProvider
if (this.options.settings.rows)
{
this.dataProvider.loadData({"rows": this.options.rows});
}
// Create the outer grid container
this.dataviewContainer = new et2_dataview_gridContainer(this.div,
@ -86,6 +118,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
* Destroys all
*/
destroy: function() {
// Free the grid components
this.dataviewContainer.free();
this.dataProvider.free();
this.dynheight.free();
@ -93,6 +126,23 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
this._super.apply(this, arguments);
},
/**
* Loads the nextmatch settings
*/
transformAttributes: function(_attrs) {
this._super.apply(this, arguments);
if (this.id)
{
var entry = this.getArrayMgr("content").getEntry(this.id);
if (entry)
{
_attrs["settings"] = entry;
}
}
},
/**
* Implements the et2_IResizeable interface - lets the dynheight manager
* update the width and height and then update the dataview container.
@ -109,8 +159,10 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
getRows: function(_fetchList, _callback, _context) {
// Create an ajax-request
var request = new egw_json_request(
"etemplate_widget_nextmatch::ajax_get_rows::etemplate", [_fetchList],
this);
"etemplate_widget_nextmatch::ajax_get_rows::etemplate", [
this.getInstanceManager().etemplate_exec_id,
_fetchList
], this);
// Send the request
request.sendRequest(true, function(_data) {
@ -126,7 +178,12 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
* descending. If not set, the sort direction will be determined
* automatically.
*/
sortBy: function(_id, _asc) {
sortBy: function(_id, _asc, _update) {
if (typeof _update == "undefined")
{
_update = true;
}
// Create the "sort" entry in the active filters if it did not exist
// yet.
if (typeof this.activeFilters["sort"] == "undefined")
@ -157,8 +214,10 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
_widget.setSortmode((_widget.id == _id) ? (_asc ? "asc": "desc") : "none");
}, this, et2_INextmatchSortable);
et2_debug("info", "Sorting nextmatch by '" + _id + "' in direction '" +
(_asc ? "asc" : "desc") + "'");
if (_update)
{
this.applyFilters();
}
},
/**
@ -182,6 +241,11 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
applyFilters: function() {
et2_debug("info", "Changing nextmatch filters to ", this.activeFilters);
// Clear the dataprovider and the dataview container - this will cause
// the grid to reload.
this.dataProvider.clear();
this.dataviewContainer.clear();
},
/**
@ -305,6 +369,43 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
this.iterateOver(function (_node) {
_node.setNextmatch(this);
}, this, et2_INextmatchHeader);
// Load the default sort order
if (this.options.settings.order && this.options.settings.sort)
{
this.sortBy(this.options.settings.order,
this.options.settings.sort == "ASC", false);
}
}
},
/**
* Activates the actions
*/
set_settings: function(_settings) {
if (_settings.actions)
{
// Read the actions from the settings array
// this.actionManager.updateActions(_settings.actions);
this.actionManager.updateActions(
[
{
"id": "view",
"iconUrl": "imgs/view.png",
"caption": "View",
"allowOnMultiple": false,
"type": "popup",
"default": true
},
{
"id": "edit",
"iconUrl": "imgs/edit.png",
"caption": "Edit file",
"allowOnMultiple": false,
"type": "popup"
}
]
);
}
},