Skip to content
Extraits de code Groupes Projets
Valider 0a30bcff rédigé par mattpiwik's avatar mattpiwik
Parcourir les fichiers

DataTable ajax rendering, 30% done

git-svn-id: http://dev.piwik.org/svn/trunk@57 59fd770c-687e-43c8-a1e3-f5a4ff64c105
parent 713b9f4b
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 447 ajouts et 171 suppressions
......@@ -35,9 +35,3 @@ Use cases
7 - Plugin that add a selection for every user
------------------------------------------------------------------------------------
......@@ -44,6 +44,7 @@ time_before_archive_considered_outdated = 3
action_category_delimiter = /
dataTable_default_limit = 10
[LogStats]
; set to 0 if you want to stop tracking the visitors. Useful if you need to stop all the connections on the DB.
......
......@@ -26,30 +26,6 @@ require_once PIWIK_INCLUDE_PATH . "/modules/ExceptionHandler.php";
set_error_handler('Piwik_ErrorHandler');
set_exception_handler('Piwik_ExceptionHandler');
/**
* Zend classes
*/
include "Zend/Exception.php";
include "Zend/Loader.php";
require_once "Zend/Debug.php";
require_once "Zend/Auth.php";
require_once "Zend/Auth/Adapter/DbTable.php";
/**
* Piwik classes
*/
require_once "Timer.php";
require_once "Piwik.php";
require_once "API/APIable.php";
require_once "Access.php";
require_once "Auth.php";
require_once "API/Proxy.php";
require_once "Site.php";
require_once "Translate.php";
require_once "Url.php";
require_once "Controller.php";
require_once "FrontController.php";
$controller = new Piwik_FrontController;
......
......@@ -30,12 +30,18 @@ class Piwik_API_Request
{
$requestArray = $_REQUEST;
// If an array is specified we use it
if(!is_null($request))
{
$request = trim($request);
$request = str_replace(array("\n","\t"),'', $request);
parse_str($request, $requestArray);
// but we handle the case when an array is specified but we also want
// to look for the value in the _REQUEST
$requestArray = array_merge( $_REQUEST, $requestArray);
}
$this->requestToUse = $requestArray;
}
......@@ -131,7 +137,9 @@ class Piwik_API_Request
}
if(empty($toReturn))
if(!is_array($toReturn) // an empty array is not considered as "nothing has been returned"
&& empty($toReturn))
{
$format = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse);
$toReturn = $this->getStandardSuccessOutput($format);
......@@ -164,7 +172,11 @@ class Piwik_API_Request
$return = '{"result":"success", "message":"ok"}';
break;
case 'php':
$return = serialize(array('result' => 'success', 'message' => 'ok'));
$return = array('result' => 'success', 'message' => 'ok');
if($this->caseRendererPHPSerialize())
{
$return = serialize($return);
}
break;
default:
$return = 'Success:ok';
......@@ -191,7 +203,11 @@ class Piwik_API_Request
$return = '{"result":"error", "message":"'.htmlentities($message).'"}';
break;
case 'php':
$return = serialize(array('result' => 'error', 'message' => $message));
$return = array('result' => 'error', 'message' => $message);
if($this->caseRendererPHPSerialize())
{
$return = serialize($return);
}
break;
default:
$return = 'Error:'.$message;
......@@ -209,29 +225,38 @@ class Piwik_API_Request
{
// Renderer
$format = Piwik_Common::getRequestVar('format', 'php', 'string', $this->requestToUse);
$renderer = Piwik_DataTable_Renderer::factory($format);
$renderer->setTable($dataTable);
$toReturn = (string)$renderer;
if($format == 'php')
{
$renderer->setSerialize( $this->caseRendererPHPSerialize());
}
$toReturn = $renderer->render();
return $toReturn;
}
/**
* Applys generic filters to the DataTable object resulting from the API Call.
* @return void
*/
protected function applyDataTableGenericFilters($dataTable)
function caseRendererPHPSerialize()
{
$serialize = Piwik_Common::getRequestVar('serialize', 1, 'int', $this->requestToUse);
if($serialize)
{
return true;
}
else
{
return false;
}
}
public static function getGenericFiltersInformation()
{
// Generic filters
// PatternFileName => Parameter names to match to constructor parameters
/*
* Order to apply the filters:
* 1 - Filter that remove filtered rows
* 2 - Filter that sort the remaining rows
* 3 - Filter that keep only a subset of the results
*/
$genericFilters = array(
'Pattern' => array(
'filter_column' => array('string'),
'filter_pattern' => array('string'),
......@@ -245,11 +270,32 @@ class Piwik_API_Request
'filter_sort_order' => array('string', 'desc'),
),
'Limit' => array(
'filter_offset' => array('integer'),
'filter_limit' => array('integer'),
'filter_offset' => array('integer', '0'),
'filter_limit' => array('integer', Zend_Registry::get('config')->General->dataTable_default_limit),
),
);
return $genericFilters;
}
/**
* Applys generic filters to the DataTable object resulting from the API Call.
* @return void
*/
protected function applyDataTableGenericFilters($dataTable)
{
// Generic filters
// PatternFileName => Parameter names to match to constructor parameters
/*
* Order to apply the filters:
* 1 - Filter that remove filtered rows
* 2 - Filter that sort the remaining rows
* 3 - Filter that keep only a subset of the results
*/
$genericFilters = Piwik_API_Request::getGenericFiltersInformation();
foreach($genericFilters as $filterName => $parameters)
{
$filterParameters = array();
......@@ -274,6 +320,7 @@ class Piwik_API_Request
}
catch(Exception $e)
{
// print($e->getMessage());
$exceptionRaised = true;
break;
}
......@@ -281,6 +328,7 @@ class Piwik_API_Request
if(!$exceptionRaised)
{
// var_dump($filterParameters);
assert(count($filterParameters)==count($parameters));
// a generic filter class name must follow this pattern
......
......@@ -181,6 +181,10 @@ class Piwik_Common
{
if(is_int($value) || $value==(int)$value) $ok = true;
}
elseif($varType == 'float')
{
if(is_float($value) || $value==(float)$value) $ok = true;
}
elseif($varType == 'array')
{
if(is_array($value)) $ok = true;
......
......@@ -22,7 +22,9 @@ class Piwik_DataTable_Filter_ColumnCallback extends Piwik_DataTable_Filter
{
foreach($this->table->getRows() as $key => $row)
{
if( !call_user_func( $this->function, $row->getColumn($this->columnToFilter)))
$columnValue = $row->getColumn($this->columnToFilter);
if( $columnValue !== false
&& !call_user_func( $this->function, $columnValue))
{
$this->table->deleteRow($key);
}
......
......@@ -13,7 +13,22 @@ class Piwik_DataTable_Renderer_PHP extends Piwik_DataTable_Renderer
function __construct($table = null, $serialize = true)
{
parent::__construct($table);
$this->serialize = $serialize;
$this->setSerialize($serialize);
}
function setSerialize( $bool )
{
$this->serialize = $bool;
}
function __toString()
{
$data = $this->render();
if(!is_string($data))
{
$data = serialize($data);
}
return $data;
}
function render()
......
<?php
/**
* Zend classes
*/
include "Zend/Exception.php";
include "Zend/Loader.php";
require_once "Zend/Debug.php";
require_once "Zend/Auth.php";
require_once "Zend/Auth/Adapter/DbTable.php";
/**
* Piwik classes
*/
require_once "Timer.php";
require_once "Piwik.php";
require_once "API/APIable.php";
require_once "Access.php";
require_once "Auth.php";
require_once "API/Proxy.php";
require_once "Site.php";
require_once "Translate.php";
require_once "Url.php";
require_once "Controller.php";
class Piwik_FrontController
{
function dispatch()
......@@ -27,6 +52,7 @@ class Piwik_FrontController
$controller->$action();
} catch(Piwik_Access_NoAccessException $e) {
Piwik::log("NO ACCESS EXCEPTION =>");
Piwik_PostEvent('FrontController.NoAccessException', $e);
}
}
......@@ -37,9 +63,8 @@ class Piwik_FrontController
}
else
{
throw new Exception("Invalid module name");
throw new Exception("Invalid module name '$module'");
}
}
function end()
......
<?php
class Piwik_ExamplePlugin_Controller extends Piwik_Controller
{
function getDefaultAction()
{
return 'homepage';
}
function homepage()
{
// invoke view
// render view
// do stuff...
}
}
......@@ -434,8 +434,7 @@ function main()
&filter_limit=10
&filter_offset=0
&idSubtable=3090
'
);
');
dump(htmlentities($request->process()));
......
function getDeleteSiteAJAX( idsite )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
// prepare the API parameters to update the user
var parameters = new Object;
parameters.module = 'API';
parameters.format = 'json';
parameters.method = 'SitesManager.deleteSite';
parameters.idSite = idsite;
ajaxRequest.data = parameters;
return ajaxRequest;
}
function getAddSiteAJAX( row )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
// prepare the API parameters to add the user
var parameters = new Object;
var name = $(row).find('input[@id=siteadd_name]').val();
var urls = $(row).find('textarea[@id=siteadd_urls]').val();
var aUrls = urls.trim().split("\n");
var request = '';
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.addSite';
request += '&name='+escape(name);
$.each(aUrls, function (key,value){ request+= '&aUrls[]='+escape(value);} );
ajaxRequest.data = request;
return ajaxRequest;
}
function getUpdateSiteAJAX( row )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
var name = $(row).find('input[@id=name]').val();
var idSite = $(row).children('#idSite').html();
var aUrls = $(row).find('textarea[@id=aUrls]').val().trim().split("\n");
var request = '';
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.updateSite';
request += '&name='+escape(name);
request += '&idSite='+idSite;
$.each(aUrls, function (key,value){ if(value.length>1) request+= '&aUrls[]='+value;} );
ajaxRequest.data = request;
return ajaxRequest;
}
$('#addRowSite').click( function() {
ajaxHideError();
$(this).toggle();
......@@ -94,7 +160,6 @@ function submitSiteOnEnter(e)
var key=e.keyCode || e.which;
if (key==13)
{
alert('ok');
$(this).parent().find('#updateSite').click();
$(this).find('#addsite').click();
}
......
......@@ -16,6 +16,7 @@ textarea{
</style>
{/literal}
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="themes/default/common.js"></script>
<h2>Sites</h2>
<div id="ajaxError" style="display:none"></div>
......
<?php
require_once "API/Request.php";
class Piwik_UserSettings_Controller extends Piwik_Controller
{
function index()
{
$view = new Piwik_View('UserSettings/templates/index.tpl');
$view->dataTableResolution = $this->getResolution(true);
echo $view->render();
}
function getResolution( $fetch = false)
{
$request = new Piwik_API_Request('
method=UserSettings.getResolution
&format=php
&serialize=0
');
$data = $request->process();
// var_dump( $data );exit;
$view = new Piwik_View('UserSettings/templates/datatable.tpl');
$view->id = 'UserSettingsResolution';
$view->dataTable = $data;
$javascriptVariablesToSet = array();
$genericFilters = Piwik_API_Request::getGenericFiltersInformation();
foreach($genericFilters as $filter)
{
foreach($filter as $filterVariableName => $filterInfo)
{
// if there is a default value for this filter variable we set it
// so that it is propagated to the javascript
if(isset($filterInfo[1]))
{
$javascriptVariablesToSet[$filterVariableName] = $filterInfo[1];
}
}
}
foreach($_GET as $name => $value)
{
$javascriptVariablesToSet[$name] = Piwik_Common::getRequestVar($name);
}
$javascriptVariablesToSet['action'] = substr(__METHOD__, strrpos(__METHOD__,':') + 1);
$view->javascriptVariablesToSet = $javascriptVariablesToSet;
$rendered = $view->render();
if($fetch)
{
return $rendered;
}
echo $rendered;
}
}
<div id="{$id}" class="parentDiv">
{if isset($dataTable.result) and $dataTable.result == 'error'}
{$dataTable.message}
{else}
<table border=1>
<tr>
<td>Label</td>
<td>Visits</td>
</tr>
{foreach from=$dataTable item=row}
<tr>
<td>{$row.columns.label}</td>
<td>{$row.columns.nb_visits}</td>
</tr>
{/foreach}
</table>
<a href="#" id="dataTablePrevious">&lt;</a> <a href="#" id="dataTableNext">&gt;</a>
<br><a href="#" id="dataTableExcludeLowPopulation">Exclude low population</a>
<script>
// to throw the ajax query we need
//- the API module+method
//- the offset / limit
//- the exclude filter
//- the sort filter
//- the pattern filter
var requestVariables = new Object;
{foreach from=$javascriptVariablesToSet key=name item=value}
requestVariables.{$name} = "{$value}";
{/foreach}
</script>
{/if}
</div>
\ No newline at end of file
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="themes/default/common.js"></script>
{literal}
<script>
$(document).ready( bindDataTableEvent );
function bindDataTableEvent()
{
$('#dataTableExcludeLowPopulation').click(
function(){
addFilter('filter_excludelowpop', 2); // add filter on the visits column
addFilter('filter_excludelowpop_value', 400.0);
reloadAjaxDataTable();
}
);
// 'filter_column' => array('string'),
// 'filter_pattern' => array('string'),
// 'filter_sort_column' => array('string', Piwik_Archive::INDEX_NB_VISITS),
// 'filter_sort_order' => array('string', 'desc'),
// 'filter_offset' => array('integer'),
// 'filter_limit' => array('integer'),
$('#dataTableNext').click(
function(){
addFilter('filter_offset', requestVariables.filter_offset + requestVariables.filter_limit);
reloadAjaxDataTable();
}
);
$('#dataTablePrevious').click(
function(){
var offset = requestVariables.filter_offset - requestVariables.filter_limit;
if(offset < 0) { offset = 0; }
addFilter('filter_offset', offset);
reloadAjaxDataTable();
}
);
}
function addFilter( nameVariable, value )
{
requestVariables[nameVariable] = value;
}
function dataTableLoaded( response )
{
var idToReplace = $(response).attr('id');
$('#'+idToReplace).html(response);
bindDataTableEvent();
}
function ajaxHandleError()
{
alert('error!');
}
function getAjaxRequest()
{
var ajaxRequest = new Object;
//prepare the ajax request
ajaxRequest.type = 'GET';
ajaxRequest.url = 'index.php';
ajaxRequest.dataType = 'html';
ajaxRequest.error = ajaxHandleError;
ajaxRequest.success = dataTableLoaded;
// $.each(requestVariables, function (key,value){ alert(key+' = '+value); } );
ajaxRequest.data = requestVariables;
return ajaxRequest;
}
function reloadAjaxDataTable()
{
var request = getAjaxRequest();
$.ajax(request);
}
function toString( object )
{
var str='';
$.each(object, function (key,value){ alert(key+' = '+value); } );
return str;
}
</script>
{/literal}
<h1>User Settings<h1>
<h2>Resolutions</h2>
{$dataTableResolution}
<h2>Browsers</h2>
{* ataTableBrowsers} *}
\ No newline at end of file
function ajaxHandleError()
{
alert('Transfer error, please reload the page or try again later.');
}
function ajaxShowError( string )
{
$('#ajaxError').html(string).show();
}
function ajaxHideError()
{
$('#ajaxError').hide();
}
function ajaxToggleLoading()
{
$('#ajaxLoading').toggle();
}
function ajaxHandleResponse(response)
{
if(response.result == "error")
{
ajaxShowError(response.message);
}
else
{
window.location.reload();
}
ajaxToggleLoading();
}
function getStandardAjaxConf()
{
var ajaxRequest = new Object;
//prepare the ajax request
ajaxRequest.type = 'GET';
ajaxRequest.url = 'index.php';
ajaxRequest.dataType = 'json';
ajaxRequest.error = ajaxHandleError;
ajaxRequest.success = ajaxHandleResponse;
return ajaxRequest;
}
function toggleAjaxLoading()
{
$('#ajaxLoading').toggle();
}
function getUpdateUserAJAX( row )
{
var ajaxRequest = getStandardAjaxConf();
......@@ -172,74 +126,6 @@ function bindUpdateAccess()
}
function getDeleteSiteAJAX( idsite )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
// prepare the API parameters to update the user
var parameters = new Object;
parameters.module = 'API';
parameters.format = 'json';
parameters.method = 'SitesManager.deleteSite';
parameters.idSite = idsite;
ajaxRequest.data = parameters;
return ajaxRequest;
}
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
}
function getAddSiteAJAX( row )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
// prepare the API parameters to add the user
var parameters = new Object;
var name = $(row).find('input[@id=siteadd_name]').val();
var urls = $(row).find('textarea[@id=siteadd_urls]').val();
var aUrls = urls.trim().split("\n");
var request = '';
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.addSite';
request += '&name='+escape(name);
$.each(aUrls, function (key,value){ request+= '&aUrls[]='+escape(value);} );
ajaxRequest.data = request;
return ajaxRequest;
}
function getUpdateSiteAJAX( row )
{
var ajaxRequest = getStandardAjaxConf();
toggleAjaxLoading();
var name = $(row).find('input[@id=name]').val();
var idSite = $(row).children('#idSite').html();
var aUrls = $(row).find('textarea[@id=aUrls]').val().trim().split("\n");
var request = '';
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.updateSite';
request += '&name='+escape(name);
request += '&idSite='+idSite;
$.each(aUrls, function (key,value){ request+= '&aUrls[]='+value;} );
ajaxRequest.data = request;
return ajaxRequest;
}
var alreadyEdited = new Array;
// when click on edituser, the cells become editable
$('.edituser')
......
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="themes/default/common.js"></script>
{literal}
......
function ajaxHandleError()
{
alert('Transfer error, please reload the page or try again later.');
}
function ajaxShowError( string )
{
$('#ajaxError').html(string).show();
}
function ajaxHideError()
{
$('#ajaxError').hide();
}
function ajaxToggleLoading()
{
$('#ajaxLoading').toggle();
}
function ajaxHandleResponse(response)
{
if(response.result == "error")
{
ajaxShowError(response.message);
}
else
{
window.location.reload();
}
ajaxToggleLoading();
}
function toggleAjaxLoading()
{
$('#ajaxLoading').toggle();
}
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
}
function getStandardAjaxConf()
{
var ajaxRequest = new Object;
//prepare the ajax request
ajaxRequest.type = 'GET';
ajaxRequest.url = 'index.php';
ajaxRequest.dataType = 'json';
ajaxRequest.error = ajaxHandleError;
ajaxRequest.success = ajaxHandleResponse;
return ajaxRequest;
}
\ No newline at end of file
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter