Add charts to membership reports
Add a custom chartjs module to integrate chart.js with Drupal. Extend the membership report by a bar chart, and the membership history report by a line chart. Change-Id: Ifb134b632e593c88d81b44e97cb1a2c73626f0a8
This commit is contained in:
parent
a374e6399f
commit
dd91ea8974
@ -688,3 +688,8 @@ libraries[feeds_jsonpath_parser][download][type] = get
|
||||
libraries[feeds_jsonpath_parser][download][url] = http://jsonpath.googlecode.com/files/jsonpath-0.8.1.php
|
||||
libraries[feeds_jsonpath_parser][destination] = modules/contrib
|
||||
libraries[feeds_jsonpath_parser][install_path] = profiles/groups
|
||||
|
||||
libraries[chartjs][download][type] = "get"
|
||||
libraries[chartjs][type] = "libraries"
|
||||
libraries[chartjs][download][url] = "https://github.com/nnnick/Chart.js/archive/v1.0.1.tar.gz"
|
||||
libraries[chartjs][destination] = "libraries"
|
@ -313,6 +313,16 @@ function groups_update_7115() {
|
||||
drupal_flush_all_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable chartjs module.
|
||||
*/
|
||||
function groups_update_7116() {
|
||||
if (!module_exists('chartjs')) {
|
||||
module_enable(array('chartjs'));
|
||||
}
|
||||
drupal_flush_all_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set language negotiation to URL based.
|
||||
*/
|
||||
|
9
modules/custom/chartjs/chartjs.info
Normal file
9
modules/custom/chartjs/chartjs.info
Normal file
@ -0,0 +1,9 @@
|
||||
name = Chart.js
|
||||
description = Charting module for Drupal based on Chart.js javascript library.
|
||||
core = 7.x
|
||||
|
||||
dependencies[] = libraries (>=2.0)
|
||||
|
||||
version = "7.x-1.0"
|
||||
core = "7.x"
|
||||
project = "chartjs"
|
40
modules/custom/chartjs/chartjs.install
Normal file
40
modules/custom/chartjs/chartjs.install
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update, and uninstall functions for the chartjs module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*/
|
||||
function chartjs_requirements($phase) {
|
||||
$requirements = array();
|
||||
|
||||
if ($phase == 'runtime') {
|
||||
$libraries = array(
|
||||
'chartjs' => 'Chart.js',
|
||||
);
|
||||
foreach ($libraries as $lib => $label) {
|
||||
$requirements['chartjs_' . $lib] = array(
|
||||
'title' => t('Chart.js: @library library', array('@library' => $label)),
|
||||
'value' => t('The @library library is not present', array('@library' => $label)),
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
);
|
||||
if (function_exists('libraries_detect')) {
|
||||
if (($library = libraries_detect($lib)) && !empty($library['installed'])) {
|
||||
$requirements['chartjs_' . $lib]['value'] = t('@version (@variant)', array(
|
||||
'@version' => $library['version'],
|
||||
'@variant' => TRUE
|
||||
));
|
||||
$requirements['chartjs_' . $lib]['severity'] = REQUIREMENT_OK;
|
||||
}
|
||||
elseif (!empty($library['error'])) {
|
||||
$requirements['chartjs_' . $lib]['description'] = $library['error message'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $requirements;
|
||||
}
|
56
modules/custom/chartjs/chartjs.module
Normal file
56
modules/custom/chartjs/chartjs.module
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_libraries_info().
|
||||
*
|
||||
* @see Libraries module.
|
||||
*/
|
||||
function chartjs_libraries_info() {
|
||||
$libraries['chartjs'] = array(
|
||||
'name' => 'Chart.js',
|
||||
'vendor url' => 'http://www.chartjs.org/',
|
||||
'download url' => 'https://github.com/nnnick/Chart.js/archive/v1.0.1.tar.gz',
|
||||
// 'version callback' => 'short_circuit_version',
|
||||
'version arguments' => array(
|
||||
'file' => 'Chart.js',
|
||||
'pattern' => '/Version: (\d+\.+\d+\.+\d+)/',
|
||||
'lines' => 4,
|
||||
),
|
||||
'files' => array(
|
||||
'js' => array(
|
||||
'Chart.js',
|
||||
),
|
||||
),
|
||||
);
|
||||
return $libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_element_info()
|
||||
*/
|
||||
function chartjs_element_info() {
|
||||
require_once 'chartjs_elements.inc';
|
||||
return _chartjs_element_info();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme()
|
||||
*/
|
||||
function chartjs_theme($existing, $type, $theme, $path) {
|
||||
require_once 'chartjs_elements.inc';
|
||||
return _chartjs_theme($existing, $type, $theme, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new dataset with defaults
|
||||
*/
|
||||
function chartjs_create_dataset($data = array()) {
|
||||
$dataSet = new stdClass();
|
||||
$dataSet->label = 'Dataset label';
|
||||
$dataSet->fillColor = 'rgba(128,197,229,1)';
|
||||
$dataSet->strokeColor = 'rgba(128,197,229,1)';
|
||||
$dataSet->highlightFill = 'rgba(0,153,218,1)';
|
||||
$dataSet->highlightStroke = 'rgba(0,153,218,1)';
|
||||
$dataSet->data = $data;
|
||||
return $dataSet;
|
||||
}
|
70
modules/custom/chartjs/chartjs_elements.inc
Normal file
70
modules/custom/chartjs/chartjs_elements.inc
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define custom chartjs form elements.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implement hook_element_info()
|
||||
*/
|
||||
function _chartjs_element_info() {
|
||||
$types['chart'] = array(
|
||||
'#input' => TRUE,
|
||||
'#theme' => 'chartjs_chart',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
'#pre_render' => array('_chartjs_chart_pre_render'),
|
||||
);
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define chartjs theme callbacks.
|
||||
*/
|
||||
function _chartjs_theme($existing, $type, $theme, $path) {
|
||||
return array(
|
||||
'chartjs_chart' => array(
|
||||
'render element' => 'element',
|
||||
'file' => 'chartjs_elements.inc',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement chart pre render callback.
|
||||
*/
|
||||
function _chartjs_chart_pre_render($element) {
|
||||
libraries_load('chartjs');
|
||||
$name = isset($element['#name']) ? $element['#name'] : "chart";
|
||||
$chart_type = isset($element['#chart_type']) ? $element['#chart_type'] : "bar";
|
||||
$element['#attached']['js'] = array(
|
||||
drupal_get_path('module', 'chartjs').'/js/chart_elements.js',
|
||||
array(
|
||||
'data' => array(
|
||||
'chart_'.$name => array(
|
||||
'labels' => $element['#labels'],
|
||||
'datasets' => $element['#datasets'],
|
||||
),
|
||||
'chart_'.$name.'_options' => $element['#options'],
|
||||
'chart_'.$name.'_type' => $chart_type,
|
||||
),
|
||||
'type' => 'setting',
|
||||
)
|
||||
);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements chart theme callback.
|
||||
*/
|
||||
function theme_chartjs_chart($variables) {
|
||||
$name = isset($variables['element']['#name']) ? $variables['element']['#name'] : 'chart';
|
||||
$output = '<div class="chart-container">';
|
||||
$output .= sprintf('<canvas id="%s" ', $name);
|
||||
if (isset($variables['element']['#height'])) {
|
||||
$output .= sprintf('height="%s"', $variables['element']['#height']);
|
||||
}
|
||||
$output .= '></canvas></div>';
|
||||
// $output = sprintf('<div class="chart-container"><canvas id="%s" height="400px"></canvas></div>', $name);
|
||||
return $output;
|
||||
}
|
21
modules/custom/chartjs/js/chart_elements.js
Normal file
21
modules/custom/chartjs/js/chart_elements.js
Normal file
@ -0,0 +1,21 @@
|
||||
(function ($) {
|
||||
Drupal.behaviors.chartJS = {
|
||||
attach: function (context, settings) {
|
||||
$('.chart-container canvas').each( function (index, data) {
|
||||
var element_id = $(this).attr('id');
|
||||
var ctx = document.getElementById(element_id).getContext("2d");
|
||||
var data = settings['chart_' + element_id];
|
||||
var options = settings['chart_' + element_id + '_options'];
|
||||
switch (settings['chart_' + element_id + '_type']) {
|
||||
case 'bar':
|
||||
var myChart = new Chart(ctx).Bar(data, options);
|
||||
break;
|
||||
case 'line':
|
||||
var myChart = new Chart(ctx).Line(data, options);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
@ -4,4 +4,5 @@ core = 7.x
|
||||
package = Groups - Building Blocks
|
||||
version = 7.x-1.0
|
||||
project = groups_reports
|
||||
dependencies[] = elysia_cron
|
||||
dependencies[] = elysia_cron
|
||||
dependencies[] = chartjs
|
@ -43,4 +43,4 @@ function groups_reports_schema() {
|
||||
'primary key' => array('nid', 'timestamp'),
|
||||
);
|
||||
return $schema;
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +82,10 @@ function groups_reports_cronapi($op, $job = NULL) {
|
||||
*/
|
||||
function groups_reports_groups_membership_report() {
|
||||
module_load_include('inc', 'field_group_location', 'field_group_lookup');
|
||||
$chart_data = array(
|
||||
'labels' => array(),
|
||||
'datasets' => array(chartjs_create_dataset()),
|
||||
);
|
||||
$continents = _continent_get_predefined_list();
|
||||
$report = groups_report_get_regional_membership_report(time());
|
||||
$total = 0;
|
||||
@ -91,19 +95,20 @@ function groups_reports_groups_membership_report() {
|
||||
'title' => t('<a href="!url">@title</a>', array('!url' => '#'.$key, '@title' => $value)),
|
||||
'count' => isset($report['totals'][$key]) ? $report['totals'][$key] : 0,
|
||||
);
|
||||
$chart_data['labels'][] = $value;
|
||||
$chart_data['datasets'][0]->data[] = $summary[$key]['count'];
|
||||
$total += $summary[$key]['count'];
|
||||
}
|
||||
$summary['XX'] = array(
|
||||
'title' => '<b>Total</b>',
|
||||
'count' => '<b>'.$total.'</b>',
|
||||
$build['chart'] = array(
|
||||
'#type' => 'chart',
|
||||
'#labels' => $chart_data['labels'],
|
||||
'#datasets' => $chart_data['datasets'],
|
||||
'#options' => array('responsive' => true, 'maintainAspectRatio' => false),
|
||||
);
|
||||
$build['summary_table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => array(t('Continent'), t('Total members')),
|
||||
'#rows' => $summary,
|
||||
'#sticky' => FALSE,
|
||||
'#attributes' => array('id' => 'group-report-summary'),
|
||||
'#empty' => t('No membership data available.'),
|
||||
$build['totals'] = array(
|
||||
'#prefix' => '<div class="totals-container">',
|
||||
'#suffix' => '</div>',
|
||||
'#markup' => t('<span class="totals_label">Community members worldwide</span> <span class="total">@total</span> <span class="suffix">people</span>', array('@total' => $total)),
|
||||
);
|
||||
foreach ($report['rows'] as $row) {
|
||||
$data[$row['field_group_location_continent']][] = array(
|
||||
@ -136,10 +141,37 @@ function groups_reports_groups_membership_report() {
|
||||
*/
|
||||
function groups_reports_groups_membership_history_report() {
|
||||
$report = groups_report_get_members_report(time());
|
||||
$report = array_reverse($report);
|
||||
$chart_data = array(
|
||||
'labels' => array(),
|
||||
'datasets' => array(chartjs_create_dataset()),
|
||||
);
|
||||
$chart_data['datasets'][0]->strokeColor = '#0099da';
|
||||
$chart_data['datasets'][0]->fillColor = '#d7edfb';
|
||||
$chart_data['datasets'][0]->pointColor = '#0099da';
|
||||
$chart_data['datasets'][0]->pointStrokeColor = '#0099da';
|
||||
$chart_data['datasets'][0]->pointHighlightFill = '#000000';
|
||||
$chart_data['datasets'][0]->pointHighlightStroke = '#000000';
|
||||
foreach ($report as &$item) {
|
||||
$item['timestamp'] = format_date($item['timestamp'], 'custom', 'm/d/Y', 'GMT');
|
||||
$chart_data['labels'][] = $item['timestamp'];
|
||||
$chart_data['datasets'][0]->data[] = $item['count'];
|
||||
}
|
||||
$report = array_reverse($report);
|
||||
$build['chart'] = array(
|
||||
'#type' => 'chart',
|
||||
'#chart_type' => 'line',
|
||||
'#name' => 'membership-history-chart',
|
||||
'#height' => '300px',
|
||||
'#labels' => $chart_data['labels'],
|
||||
'#datasets' => $chart_data['datasets'],
|
||||
'#options' => array(
|
||||
'responsive' => true,
|
||||
'maintainAspectRatio' => false,
|
||||
'datasetFill' => true,
|
||||
'bezierCurve' => false,
|
||||
'datasetStrokeWidth' => 3,
|
||||
),
|
||||
);
|
||||
$header = array(t('Date'), t('Members'));
|
||||
$build['summary_table'] = array(
|
||||
'#theme' => 'table',
|
||||
|
@ -12,4 +12,30 @@
|
||||
th, td {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.totals-container {
|
||||
background: #EDF2F7;
|
||||
padding: 10px;
|
||||
.totals_label {
|
||||
color: #2A4E68;
|
||||
font-size: 30px;
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
margin-right: 10px;
|
||||
border-right: 4px solid #ffffff;
|
||||
}
|
||||
.total {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.suffix {
|
||||
color: #2A4E68;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
|
||||
#membership-history-chart {
|
||||
height: 400px;
|
||||
}
|
Loading…
Reference in New Issue
Block a user