Commit 80b7f84b authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Merge "Bug 853662: Replacing the pear graphing for chartjs graphing."

parents a1f5bc7e 23b58ab7
......@@ -65,13 +65,14 @@ addLoadEvent(function () {
});
EOF;
$smarty = smarty(array('paginator'));
$smarty = smarty(array('paginator','js/chartjs/Chart.min.js'));
setpageicon($smarty, 'icon-area-chart');
$smarty->assign('PAGEHEADING', TITLE);
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign('sitedata', $sitedata);
$smarty->assign('type', $type);
$smarty->assign('subpages', $subpages);
......
......@@ -100,7 +100,7 @@ addLoadEvent(function() {
});
EOF;
$smarty = smarty(array('paginator'));
$smarty = smarty(array('paginator','js/chartjs/Chart.min.js'));
setpageicon($smarty, 'icon-university');
$smarty->assign('PAGEHEADING', TITLE);
......
......@@ -1027,3 +1027,71 @@ var is_page_ready = false;
jQuery(document).ready(function() {
is_page_ready = true;
});
/**
* Calls statistical data from the db and returns Chart.js structured json
*
* @param object opts Any options we need to pass in to get correct data
* Can contain:
* id - the id of the canvas to put the graph in. The legend id should be id + 'legend'
* type - the type of graph we want to display, eg line/bar/pie etc
* graph - the name of the function to fetch the data from, eg 'group_type_graph'
* colours - an array of rgb colours eg "['200,100,37','123,21,103']"
*
* @return object data A json encoded object acceptable to Chart.js
* - see Chart.js for json shape.
*/
var chartobject;
var canvascontext;
function fetch_graph_data(opts) {
if (typeof opts.extradata != 'undefined') {
opts.extradata = JSON.stringify(opts.extradata);
}
if (typeof opts.colours != 'undefined') {
opts.colours = JSON.stringify(opts.colours);
}
if (!document.getElementById(opts.id + 'legend')) {
// We need to add in the legend container
var legend = document.createElement('div');
legend.id = opts.id + 'legend';
legend.className = 'graphlegend';
var canvas = document.getElementById(opts.id);
canvas.parentNode.insertBefore(legend, canvas.nextSibling);
}
if (!document.getElementById(opts.id + 'title')) {
// We need to add in the title container
var title = document.createElement('div');
title.id = opts.id + 'title';
title.className = 'graphtitle';
var canvas = document.getElementById(opts.id);
canvas.parentNode.insertBefore(title, canvas);
}
sendjsonrequest(config.wwwroot + 'json/graphdata.php', opts, 'POST', function (json) {
if (json.data.empty == true) {
document.getElementById(opts.id).style.display = 'none';
}
else {
if (document.getElementById(opts.id + 'legend').hasChildNodes()) {
// We already have a chart with this id so we need to clear its data
chartobject.destroy();
document.getElementById(opts.id + 'legend').innerHTML = '';
document.getElementById(opts.id + 'title').innerHTML = '';
}
else {
canvascontext = document.getElementById(opts.id).getContext("2d");
}
chartobject = new Chart(canvascontext)[json.data.graph](JSON.parse(json.data.datastr));
var legendHolder = document.createElement('div');
legendHolder.innerHTML = chartobject.generateLegend();
document.getElementById(opts.id + 'legend').appendChild(legendHolder.firstChild);
if (json.data.title) {
jQuery('#' + opts.id + 'title').text(json.data.title);
}
}
});
}
<?php
/**
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
if (!defined('INTERNAL')) {
define('INTERNAL', 1);
}
require_once(dirname(dirname(__FILE__)) . '/init.php');
if (!defined('CRON')) {
define('JSON', 1);
json_headers();
$validtypes = array('Line', 'Bar', 'Radar', 'PolarArea', 'Pie', 'Doughnut');
$type = ucfirst(param_alphanum('type', false));
if (!in_array($type, $validtypes)) {
json_reply('missingparameter', '\'' . $type . '\' is not a valid graph type');
}
$graph = param_alphanumext('graph', null);
$colours = param_variable('colours', null);
$colours = json_decode($colours);
$extradata = param_variable('extradata', null);
$extradata = json_decode($extradata);
require_once(get_config('libroot') . 'graph.php');
require_once(get_config('libroot') . 'registration.php');
if (!function_exists($graph) || !in_array($graph, allowed_graph_functions())) {
json_reply('invalidparameter', 'Cannot call graph function \'' . $graph . '\'');
}
else {
$data = ($extradata) ? $graph($type, $extradata) : $graph($type);
if (empty($data)) {
$data['empty'] = true;
json_reply(false, array('data' => $data));
}
if (!empty($data['jsondata'])) {
$data['datastr'] = $data['jsondata'];
json_reply(false, array('data' => $data));
}
$graphdata = array();
$data['colours'] = get_graph_colours($data, $colours);
// Now covert it to something Chart.js can understand
switch ($data['graph']) {
case 'Pie':
case 'PolarArea':
case 'Doughnut':
$graphdata = get_circular_graph_json($data, $colours);
break;
case 'Bar':
$graphdata = get_bar_graph_json($data, $colours);
break;
case 'Line':
$graphdata = get_line_graph_json($data, $colours);
break;
default:
}
$data['datastr'] = json_encode($graphdata);
json_reply(false, array('data' => $data));
}
}
......@@ -117,6 +117,7 @@ $string['count_blocks'] = 'Number of blocks';
$string['count_views'] = 'Number of pages';
$string['dbtype'] = 'Database type';
$string['enablenetworking'] = 'Enabled networking';
$string['grouptypes'] = 'Group types';
$string['installation_key'] = 'Installation key';
$string['lang'] = 'Language';
$string['newstats'] = 'New statistics';
......@@ -187,3 +188,9 @@ $string['view_type_grouphomepage'] = 'Number of group homepages';
$string['view_type_portfolio'] = 'Number of portfolio pages';
$string['view_type_profile'] = 'Number of profile pages';
$string['wwwroot'] = 'WWW root';
$string['sitedataweekly'] = 'Weekly site data';
$string['group-count'] = 'Groups';
$string['view-count'] = 'Views';
$string['user-count'] = 'User';
$string['institutiondataweekly'] = 'Institution weekly data';
\ No newline at end of file
<?php
/**
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*/
defined('INTERNAL') || die();
/**
* Only these functions are allowed to be called by fetch_graph_data().
*/
function allowed_graph_functions() {
return array(
'institution_view_type_graph_render',
'graph_institution_data_weekly',
'user_institution_graph',
'view_type_graph_render',
'group_type_graph_render',
'graph_site_data_weekly',
);
}
/**
* Return the chartjs structured array data for circular graphs
* Circular graphs include pie, doughnut, polar graphs
*
* @param array $data Array of information to graph
* Includes: 'data': associative array of label -> data points
* 'colours': custom colours from the function to use instead of the defaults
* 'labellang': the lang file to find the label string translation
* @param array $colours Custom colours from js to use instead of the defaults
* @param bool $cron If function is called from cron we don't want to reply via js
*
* @return array $graphdata An array structure that can be encoded to json for chartjs
*/
function get_circular_graph_json($data, $colours = null, $cron = false) {
if (empty($data['data'])) {
$data['empty'] = true;
if ($cron) {
return $data;
}
json_reply(false, array('data' => $data));
}
$data['colours'] = get_graph_colours($data, $colours);
$graphdata = array();
$x = 0;
foreach ($data['data'] as $key => $value) {
$dataobj['value'] = (int)$value;
$dataobj['color'] = "rgba(" . $data['colours'][$x] . ",1)";
$dataobj['highlight'] = "rgba(" . $data['colours'][$x] . ",0.6)";
$dataobj['label'] = !empty($data['labellang']) ? get_string($key, $data['labellang']) : $key;
$graphdata[] = $dataobj;
$x = empty($data['colours'][$x+1]) ? 0 : $x + 1;
}
return $graphdata;
}
/**
* Return the chartjs structured array data for a bar graph
*
* @param array $data Array of information to graph
* Includes: 'data': associative array of point label -> data point
* 'labels': labels for the bars
* 'colours': custom colours from the function to use instead of the defaults
* 'labellang': the lang file to find the label string translation
* @param array $colours Custom colours from js to use instead of the defaults
* @param bool $cron If function is called from cron we don't want to reply via js
*
* @return array $graphdata An array structure that can be encoded to json for chartjs
*/
function get_bar_graph_json($data, $colours = null, $cron = false) {
if (empty($data['data'])) {
$data['empty'] = true;
if ($cron) {
return $data;
}
json_reply(false, array('data' => $data));
}
$data['colours'] = get_graph_colours($data, $colours);
$graphdata = array();
$x = 0;
$graphdata['labels'] = $data['labels'];
foreach ($data['data'] as $key => $value) {
$dataobj['fillColor'] = "rgba(" . $data['colours'][$x] . ",0.5)";
$dataobj['strokeColor'] = "rgba(" . $data['colours'][$x] . ",0.8)";
$dataobj['highlightFill'] = "rgba(" . $data['colours'][$x] . ",0.75)";
$dataobj['highlightStroke'] = "rgba(" . $data['colours'][$x] . ",1)";
$dataobj['label'] = !empty($data['labellang']) ? get_string($key, $data['labellang']) : $key;
$dataobj['data'] = is_array($value) ? array_values($value) : array($value);
$graphdata['datasets'][] = $dataobj;
$x = empty($data['colours'][$x+1]) ? 0 : $x + 1;
}
return $graphdata;
}
/**
* Return the chartjs structured array data for a line graph
*
* @param array $data Array of information to graph
* Includes: 'data': associative array of point label -> data point
* 'labels': labels for the lines
* 'colours': custom colours from the function to use instead of the defaults
* 'labellang': the lang file to find the label string translation
* @param array $colours Custom colours from js to use instead of the defaults
* @param bool $cron If function is called from cron we don't want to reply via js
*
* @return array $graphdata An array structure that can be encoded to json for chartjs
*/
function get_line_graph_json($data, $colours = null, $cron = false) {
if (empty($data['data'])) {
$data['empty'] = true;
if ($cron) {
return $data;
}
json_reply(false, array('data' => $data));
}
$data['colours'] = get_graph_colours($data, $colours);
$graphdata = array();
$x = 0;
$graphdata['labels'] = $data['labels'];
foreach ($data['data'] as $key => $value) {
$dataobj['fillColor'] = "rgba(" . $data['colours'][$x] . ",0.2)";
$dataobj['strokeColor'] = "rgba(" . $data['colours'][$x] . ",1)";
$dataobj['pointColor'] = "rgba(" . $data['colours'][$x] . ",1)";
$dataobj['pointStrokeColor'] = "rgba(255,255,255,1)";
$dataobj['pointHighlightFill'] = "rgba(255,255,255,1)";
$dataobj['pointHighlightStroke'] = "rgba(" . $data['colours'][$x] . ",1)";
$dataobj['label'] = !empty($data['labellang']) ? get_string($key, $data['labellang']) : $key;
$dataobj['data'] = is_array($value) ? array_values($value) : array($value);
$graphdata['datasets'][] = $dataobj;
$x = empty($data['colours'][$x+1]) ? 0 : $x + 1;
}
return $graphdata;
}
/**
* Returns an array of rgb colours to use in the graph
* We use rgb colours so to allow the chartjs to use alpha transperency
*
* @param array $data Array of information to graph
* Includes: 'colours': custom colours passed in via the call to the graph function, eg view_type_graph()
* @param array $colours Array of colours passed in via ajax from fetch_graph_data()
*
* @return array The merged set of colours
*/
function get_graph_colours($data, $colours = null) {
// Using colours in rgb format to allow for the use of rgba colours in Chart.js
// 10 defaults: Red, Green, Blue, Yellow, Sky blue, Magenta, Orange, Light blue, Grey, Purple
$defaultcolours = ['255,0,0','0,255,0','0,0,255','255,255,0','0,255,255','255,0,255','255,128,0','0,128,255','128,128,128','128,0,255'];
// We try to set colours in this order:
// passed in by user overides
// passed in by function overides
// defaults
if (is_array($colours)) {
if (!empty($data['colours']) && is_array($data['colours'])) {
$data['colours'] = $colours + $data['colours'] + $defaultcolours;
}
else {
$data['colours'] = $colours + $defaultcolours;
}
}
else if (!empty($data['colours']) && is_array($data['colours'])) {
$data['colours'] = $data['colours'] + $defaultcolours;
}
else {
$data['colours'] = $defaultcolours;
}
return $data['colours'];
}
\ No newline at end of file
......@@ -3618,8 +3618,6 @@ function cron_site_data_weekly() {
'type' => 'view-count',
'value' => $current['views'],
));
graph_site_data_weekly();
}
function cron_site_data_daily() {
......@@ -3702,8 +3700,8 @@ function cron_site_data_daily() {
'value' => $diskusage,
));
}
graph_site_data_daily();
}
function cron_institution_data_weekly() {
......@@ -3726,9 +3724,7 @@ function cron_institution_data_weekly() {
));
$current['name'] = $institution;
graph_institution_data_weekly($current);
}
}
function cron_institution_data_daily() {
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
.graphtitle {
font-weight: bold;
}
.graphlegend ul {
list-style: none;
li {
white-space: nowrap;
display: inline-block;
padding-left: 30px;
position: relative;
margin-bottom: 4px;
border-radius: 3px;
padding: 2px 6px 2px 28px;
font-size: 0.9em;
cursor: default;
-webkit-transition: background-color 200ms ease-in-out;
-moz-transition: background-color 200ms ease-in-out;
-o-transition: background-color 200ms ease-in-out;
transition: background-color 200ms ease-in-out;
span {
display: block;
position: absolute;
left: 0;
top: 0;
width: 18px;
height: 100%;
border-radius: 3px;
}
}
}
......@@ -87,7 +87,7 @@
@import "../lib/star";
@import "../lib/tinymce";
@import "../lib/draggable";
@import "../lib/chart";
// Keep these files last to override all other style sheets
@import "../custom";
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,7 +3,16 @@
{else}
{if $groupgraph}
<img src="{$groupgraph}" alt="" class="pull-right" />
<div id="site-stats-graph" class="pull-right">
<canvas class="graphcanvas" id="sitestatsgroupgraph" width="265" height="151"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsgroupgraph','type':'doughnut','graph':'group_type_graph_render'});
});
{/literal}
</script>
</div>
{/if}
<div>
<h4>{str tag=groupcountsbytype section=admin}:</h4>
......
{if $viewcount == 0}
<p>{str tag=noviews section=view}</p>
{/if}
{if $blocktypecounts}
<p>{str tag=blockcountsbytype section=admin}:
<ul>
{foreach from=$blocktypecounts item=item}
<li>{str tag=title section=blocktype.$item->langsection}: {$item->blocks}</li>
{/foreach}
</ul>
</p>
{/if}
{if $viewtypes}
<div id="site-stats-graph">
<canvas class="graphcanvas" id="sitestatsviewtypesgraph" width="300" height="200"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsviewtypesgraph',
'type':'doughnut',
'graph':'institution_view_type_graph_render',
'extradata': {'institution': '{/literal}{$institution}{literal}'}
});
});
{/literal}
</script>
</div>
{/if}
{if $sitedata.weekly}
<div id="site-stats-graph" class="panel-body">
<img src="{$sitedata.weekly}" alt="" />
<canvas class="graphcanvas" id="sitestatsgraph" width="265" height="151"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsgraph','type':'bar','graph':'graph_site_data_weekly'});
});
{/literal}
</script>
</div>
{/if}
<table class="table">
......
{if $institutiondata.weekly}
<div id="site-stats-graph">
<img src="{$institutiondata.weekly}" alt="" />
<canvas class="graphcanvas" id="sitestatsgraph" width="265" height="151"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsgraph','type':'bar','graph':'graph_institution_data_weekly',
'extradata': {'institution': '{/literal}{$institutiondata.institution}{literal}'}
});
});
{/literal}
</script>
</div>
{/if}
<table class="table">
......@@ -46,4 +55,4 @@
{$institutiondata.diskusage|display_size}
</td>
{/if}
</table>
\ No newline at end of file
</table>
......@@ -5,6 +5,15 @@
<li class="list-group-item">{$data.strmaxgroups|safe}</li>
<li class="list-group-item">{$data.strmaxquotaused|safe}</li>
</ul>
{if $data.institutions}
<img src="{$data.institutions}" alt="" class="pull-right" />
{if $data}
<div id="site-stats-graph" class="pull-right">
<canvas class="graphcanvas" id="sitestatsusersgraph" width="300" height="300"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsusersgraph','type':'bar','graph':'user_institution_graph'});
});
{/literal}
</script>
</div>
{/if}
......@@ -4,12 +4,20 @@
{if $blocktypecounts}
<h4>{str tag=blockcountsbytype section=admin}: </h4>
{if $viewtypes}
<img src="{$viewtypes}" alt="" class="pull-right" />
<div id="site-stats-graph" class="pull-right">
<canvas class="graphcanvas" id="sitestatsviewtypesgraph" width="300" height="200"></canvas>
<script type="application/javascript">
{literal}
jQuery(function() {
fetch_graph_data({'id':'sitestatsviewtypesgraph','type':'doughnut','graph':'view_type_graph_render'});
});
{/literal}
</script>
</div>
{/if}
<ul class="list-group unstyled pull-left">
{foreach from=$blocktypecounts item=item}
<li class="list-group-item">{str tag=title section=blocktype.$item->langsection}: {$item->blocks}</li>
{/foreach}
</ul>
{/if}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment