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='') 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') 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 // Force the array to be associative
self::$request = etemplate_request::read($exec_id); 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['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 = egw_json_response::get();
$response->data($result); $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 * Stops calling _dataRow.updateData for the dataRow registered for the given
* index. * 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" "use strict"
/*egw:uses /*egw:uses
egw_action.egw_action;
et2_core_inheritance; et2_core_inheritance;
et2_core_common; et2_core_common;
et2_dataview_interfaces; et2_dataview_interfaces;
@ -23,7 +25,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
/** /**
* Creates this instance of the data provider. * Creates this instance of the data provider.
*/ */
init: function(_source, _total) { init: function(_source, _total, _actionMgr) {
this._source = _source; this._source = _source;
this._total = _total; 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._stepSize = 25; // Count of elements which is loaded at once
this._maxCount = 1000; // Maximum count before the elements are cleaned up this._maxCount = 1000; // Maximum count before the elements are cleaned up
// Create an action object manager
this.actionObjectManager = new egwActionObjectManager("", _actionMgr);
var self = this; var self = this;
this._cleanupInterval = window.setInterval(function() {self._cleanup()}, this._cleanupInterval = window.setInterval(function() {self._cleanup()},
10 * 1000); 10 * 1000);
@ -49,10 +54,33 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
window.clearInterval(this._cleanupInterval); window.clearInterval(this._cleanupInterval);
// Destroy the _queueFlushTimeout // Destroy the _queueFlushTimeout
if (this._queueFlushTimeout !== null) this._stopFlushTimer();
{
window.clearTimeout(this._queueFlushTimeout); // 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]); delete(this._registeredRows[_idx]);
}, },
getActionObjectManager: function() {
return this.actionObjectManager;
},
/* ---- PRIVATE FUNCTIONS ---- */ /* ---- PRIVATE FUNCTIONS ---- */
_queueIndex: function(_idx) { _queueIndex: function(_idx) {
@ -188,7 +220,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
_receiveData: function(_data) { _receiveData: function(_data) {
var time = (new Date).getTime(); var time = (new Date).getTime();
for (var key in _data) for (var key in _data.rows)
{ {
if (!isNaN(key)) if (!isNaN(key))
{ {
@ -197,7 +229,7 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
// Copy the data for the given index // Copy the data for the given index
this._data[key] = { this._data[key] = {
"data": _data[key], "data": _data.rows[key],
"timestamp": time "timestamp": time
}; };
@ -218,7 +250,6 @@ var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
_callUpdateData: function(_idx) { _callUpdateData: function(_idx) {
if (typeof this._registeredRows[_idx] != "undefined") if (typeof this._registeredRows[_idx] != "undefined")
{ {
// this._data[idx].timestamp = (new Date).getTime();
this._registeredRows[_idx].updateData({ this._registeredRows[_idx].updateData({
"content": this._data[_idx].data "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 // Create the partition tree object which is used to organize the tree
// items. // items.
partitionTree = this._partitionTree = new et2_dataview_partitionTree(this._dataProvider, this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
this._rowProvider, this._avgHeight, this.innerTbody); this._rowProvider, this._avgHeight, this.innerTbody);
// Setup the "rebuild" timer - it rebuilds the complete partition tree // 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(); 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. * 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 // Calculate the range of the actually shown elements
var displayTop = _range.top; var displayTop = _range.top;
var displayBottom = _range.bottom; var displayBottom = _range.bottom;

View File

@ -91,6 +91,16 @@ var et2_dataview_gridContainer = Class.extend({
this.table.remove(); 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 * Returns the column container node for the given column index
* *

View File

@ -13,8 +13,11 @@
"use strict"; "use strict";
/*egw:uses /*egw:uses
egw_action.egw_action;
et2_dataview_interfaces; et2_dataview_interfaces;
et2_dataview_view_container; et2_dataview_view_container;
et2_dataview_view_rowAOI;
*/ */
var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, { 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._idx = null;
this.rowWidget = null; this.rowWidget = null;
this.actionObject = null;
this.hasAvgHeight = false; this.hasAvgHeight = false;
// Get the default row object and scale the row to the average height // 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(); 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(); this._super();
}, },
@ -69,6 +80,23 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
}, },
updateData: function(_data) { 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 // Reset the height
if (this.hasAvgHeight) if (this.hasAvgHeight)

View File

@ -13,18 +13,33 @@
"use strict"; "use strict";
/*egw:uses /*egw:uses
// Force some base libraries to be loaded
jquery.jquery; jquery.jquery;
/phpgwapi/egw_json.js; /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_interfaces;
et2_core_DOMWidget; et2_core_DOMWidget;
// Include all widgets the nextmatch extension will create
et2_widget_template; et2_widget_template;
et2_widget_grid; et2_widget_grid;
et2_widget_selectbox; et2_widget_selectbox;
// Include the dynheight manager
et2_extension_nextmatch_dynheight; et2_extension_nextmatch_dynheight;
// Include the grid classes
et2_dataview_view_gridContainer; et2_dataview_view_gridContainer;
et2_dataview_model_dataProvider; et2_dataview_model_dataProvider;
et2_dataview_model_columns; et2_dataview_model_columns;
*/ */
/** /**
@ -56,6 +71,11 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
"name": "Template", "name": "Template",
"type": "string", "type": "string",
"description": "The id of the template which contains the grid layout." "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. // container.
this.dynheight = new et2_dynheight(null, this.div, 150); 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 // 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, 100); 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 // Create the outer grid container
this.dataviewContainer = new et2_dataview_gridContainer(this.div, this.dataviewContainer = new et2_dataview_gridContainer(this.div,
@ -86,6 +118,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
* Destroys all * Destroys all
*/ */
destroy: function() { destroy: function() {
// Free the grid components
this.dataviewContainer.free(); this.dataviewContainer.free();
this.dataProvider.free(); this.dataProvider.free();
this.dynheight.free(); this.dynheight.free();
@ -93,6 +126,23 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
this._super.apply(this, arguments); 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 * Implements the et2_IResizeable interface - lets the dynheight manager
* update the width and height and then update the dataview container. * 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) { getRows: function(_fetchList, _callback, _context) {
// Create an ajax-request // Create an ajax-request
var request = new egw_json_request( var request = new egw_json_request(
"etemplate_widget_nextmatch::ajax_get_rows::etemplate", [_fetchList], "etemplate_widget_nextmatch::ajax_get_rows::etemplate", [
this); this.getInstanceManager().etemplate_exec_id,
_fetchList
], this);
// Send the request // Send the request
request.sendRequest(true, function(_data) { 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 * descending. If not set, the sort direction will be determined
* automatically. * 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 // Create the "sort" entry in the active filters if it did not exist
// yet. // yet.
if (typeof this.activeFilters["sort"] == "undefined") 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"); _widget.setSortmode((_widget.id == _id) ? (_asc ? "asc": "desc") : "none");
}, this, et2_INextmatchSortable); }, this, et2_INextmatchSortable);
et2_debug("info", "Sorting nextmatch by '" + _id + "' in direction '" + if (_update)
(_asc ? "asc" : "desc") + "'"); {
this.applyFilters();
}
}, },
/** /**
@ -182,6 +241,11 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
applyFilters: function() { applyFilters: function() {
et2_debug("info", "Changing nextmatch filters to ", this.activeFilters); 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) { this.iterateOver(function (_node) {
_node.setNextmatch(this); _node.setNextmatch(this);
}, this, et2_INextmatchHeader); }, 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"
}
]
);
} }
}, },