Register css/js bundles and add static files

This commit is contained in:
Alejandro Avilés 2014-10-01 17:13:50 +02:00
parent 9170fc2989
commit da34111815
3 changed files with 485 additions and 0 deletions

View File

@ -27,6 +27,10 @@ class StatisticsPlugin(IndicoPlugin):
def get_blueprints(self):
return blueprint
def register_assets(self):
self.register_css_bundle('statistics_css', 'css/statistics.css')
self.register_js_bundle('statistics_js', 'js/statistics.js')
blueprint = IndicoPluginBlueprint('statistics', __name__)
blueprint.add_url_rule('/event/<confId>/manage/statistics_new', 'view', RHStatisticsView)

View File

@ -0,0 +1,167 @@
div.test {
background: red;
}
div#statsHeader {
border-bottom: 1px solid #EFEFEF;
padding-bottom: 10px;
display: block;
width: auto;
height: auto;
}
div#statsWidgetsWrapper {
width: 740px;
height: auto;
padding: 10px 0px 10px 0px;
}
div.statsInfo {
font-size: 1.2em;
}
div#statsInfoHidden {
padding-top: 5px;
display: none;
}
div#statsFilter {
clear: both;
padding-top: 5px;
display: none;
height: auto !important;
}
div.statsTopBordered {
border-top: 1px solid #EFEFEF;
padding-top: 5px;
text-align: right;
}
div.statsRow {
width: 100%;
display: block;
height: 320px;
clear: both;
}
div.statsWidget {
display: block;
border-left: 1px solid #EFEFEF;
padding: 0px 5px 0px 5px;
margin: 0px 16px 15px 0px;
float: left;
height: 100%;
}
div.statsFilterOption {
padding-bottom: 5px;
}
div.statsWidget iframe {
width: 100%;
height: 280px;
}
div.statsWidget.full {
width: 100%;
}
div.statsWidget.edge {
margin-right: 0px !important;
}
div.statsWidget.large {
width: 500px;
}
div.statsWidget.medium {
width: 350px;
}
div.statsWidget.small {
width: 200px;
}
div.statsWidgetTitle {
background: #EFEFEF;
font-weight: bold;
padding: 5px;
font-size: 1.1em;
}
div.statsWidgetContent {
width: auto;
height: 100%;
padding: 5px;
word-wrap: break-word;
}
div.statsTableDivider {
padding: 10px 0px 5px 0px;
margin-bottom: 5px;
display: block;
width: 100%;
border-bottom: 1px solid #DDDDEF;
font-weight: bold;
}
div#statsGenerated {
font-style: italic;
font-size: 0.8em;
padding-top: 10px;
}
div#materialTree {
display: block;
width: 190px;
height: 80%;
overflow: auto;
float: left;
padding: 15px 10px 10px 10px;
}
div#materialContainer {
display: block;
width: 510px;
float: left;
padding-left: 10px;
height: 90%;
}
/* jqTree Formatting */
div#materialTree ul {
margin: 0px;
padding: 0 0 0px 10px;
line-height: 1.5em;
}
div#marginTree ul ul {
padding-left: 5px;
}
span.selectableNode {
color: #0B63A5 !important;
font-size: 0.9em;
display: block;
width: auto;
border-bottom: 1px solid #EFEFEF;
}
ul.tree .title {
color: #444;
}
/* jqPlot Formatting */
div#materialDownloadChart {
width: auto;
height: 250px;
}
div#visitorChart {
margin-left: 15px;
width: 95%;
height: 270px;
}

View File

@ -0,0 +1,314 @@
$(function() {
$('#statsModify').click(function() {
var text = ($(this).html() == str_modif_query)
? str_hide_query : str_modif_query;
$(this).html(text);
$('#statsFilter').slideToggle('fast');
});
$('.statsDates').datepicker({
dateFormat : 'yy-mm-dd',
defaultDate : $(this).attr('data-default')
});
var buildURI = function() {
var params = {'confId' : $('#confId').val(),
'startDate' : $('#statsFilterStartDate').val(),
'endDate' : $('#statsFilterEndDate').val(),
'tab' : 'Piwik'
};
var updateContrib = $('#updateContribution').val();
if (updateContrib != 'None') {
params['contribId'] = updateContrib;
}
return $.param(params);
};
/**
* Reconstruct the query string based on local values and force relocation.
*/
$('#updateQuery').click(function() {
var url = 'statistics?';
url += buildURI();
window.location.href = url;
});
/**
* Provides the 'info' tooltip handling for Visitor Hit Rates
*/
$('#visitsInfoHelp').qtip({
content: $('#statsInfoHidden').html(),
position: {
my: 'top middle',
at: 'bottom middle'
},
style: {
classes: 'qtip-rounded qtip-shadow qtip-light'
}
});
/* jqPlot Specifics */
/**
* This method extracts the data from the JSON returned via the API into
* the array format which jqPlot requires. Specifying 'withDate' as true
* makes each element of the array a key-pair value of date-hits for the
* renderer jqPlot provides.
*/
var getArrayValues = function(data, key, withDate) {
output = [];
withDate = typeof withDate !== 'undefined' ? withDate : true;
for (var date in data) {
hits = data[date];
value = (withDate) ? [date, hits[key]] : hits[key];
output.push(value);
}
return output;
};
/**
* Clears the DOM element for the graph and then initiates a jqPlot render
* in the target area.
*
* @param source - JSON of dates: {total / unique} hits
*/
var drawGraph = function(source, DOMTarget, replot) {
// Clear the DOM target
$('#' + DOMTarget).html('');
var plotOptions = {
axes: {
xaxis: {
renderer:$.jqplot.DateAxisRenderer,
min: reportDates.start,
max: reportDates.end
},
yaxis: {
min: 0,
numberTicks: 10
}
},
cursor: {
show: true,
zoom: true,
showTooltip: false
},
highlighter: {
show: true,
sizeAdjust: 5
},
legend: {
show: true,
location: 'nw'
},
grid: {
background: '#FFFFFF',
shadow: false
},
series: [{
showMarker:false,
lineWidth: 1,
color: '#CCCCCC',
label: $T('Total Hits')
}, {
showMarker:false,
lineWidth: 1,
color: '#0B63A5',
label: $T('Unique Hits')
}]
};
// Create the plot here
if (replot) {
$.jqplot(DOMTarget, source, plotOptions).replot();
} else {
$.jqplot(DOMTarget, source, plotOptions);
}
};
/**
* Base values for API requests, to be extended as needed.
*/
var getIndicoBaseParams = function() {
var indicoBaseParams = {
startDate: $('#statsFilterStartDate').val(),
endDate: $('#statsFilterEndDate').val(),
confId: $('#confId').val()
};
var contribId = $('#contribId').val();
// We only want to append if it's not the internal 'None' flag.
if (contribId != 'None') {
indicoBaseParams['contribId'] = contribId;
}
return indicoBaseParams;
};
/**
* Loads hit rate data via AJAX to propagate the main Visitors Graph.
*/
var loadVisitorsGraph = function(data) {
var DOMTarget = 'visitorChart';
$('#' + DOMTarget).html(progressIndicator(true, true).dom);
indicoRequest('piwik.getEventVisits', getIndicoBaseParams(),
function(result, error) {
if (!error) {
var source = [getArrayValues(result, 'total_hits'),
getArrayValues(result, 'unique_hits')]
drawGraph(source, DOMTarget, false);
} else {
$('#' + DOMTarget).html($T('No data found.'));
}
});
};
/**
* Loads material data via AJAX to propagate Material Graph(s)
*/
var loadMaterialGraph = function(uri, replot) {
replot = typeof replot !== 'undefined' ? replot : false;
var DOMTarget = 'materialDownloadChart';
var graphParams = getIndicoBaseParams();
graphParams['materialURL'] = uri;
indicoRequest('piwik.getMaterialStatistics', graphParams,
function(result, error) {
if (!error) {
if (result !== null) {
var materialHits = [getArrayValues(result['individual'],
'total_hits'),
getArrayValues(result['individual'],
'unique_hits')];
drawGraph(materialHits, DOMTarget, replot);
// Write to the title the total material downloads
$('#materialTotalDownloads').html(result['cumulative']['total_hits']);
}
} else {
$('#dialogNoGraphData').dialog('open');
}
}
);
};
/* jqTree Specifics */
var treeDOMTarget = '#materialTree';
/**
* Handles all the specific jqTree customization required.
*/
var drawTree = function(treeData) {
$(treeDOMTarget).tree(
{
data: treeData,
autoOpen: 0,
saveState: true,
onCanSelectNode: function(node) {
/* If this node has no children, it is material - ergo, make it
* selectable so that the event binding can work. */
return (node.children.length == 0)
},
onCreateLi: function(node, $li) {
if (node.id !== undefined) {
$li.find('.title').addClass('selectableNode');
}
}
});
}
/**
* Loads the data required for jqTree via AJAX and then delegates this
* data to drawTree for DOM insertion.
*/
var loadTree = function() {
var materialTreeData = null;
/* Placeholder loading spinner for larger events. */
$(treeDOMTarget).html(progressIndicator(true, true).dom);
indicoRequest('piwik.getMaterialTreeData',
{
confId: $('#confId').val()
},
function(result, error) {
if (!error) {
if (result !== null) {
drawTree(result);
} else {
/* There is no material present */
$(treeDOMTarget).html($T('No Material Found.'));
}
}
});
};
/**
* Event handler for clicking 'selectable' elements from the jqTree.
*/
$(treeDOMTarget).bind('tree.click', function(event) {
$('#materialTitle').html(event.node.name);
$('#materialDownloadChart').html(progressIndicator(true, true).dom);
loadMaterialGraph(event.node.id, true);
});
/**
* jQuery UI Dialog if no data is received via AJAX (timeout)
*/
$('#dialogNoGraphData').dialog({
modal: true,
resizable: false,
autoOpen: false,
buttons: {
Ok: function() {
$(this).dialog('close');
}
}
});
/* Static graph data being retrieved by the API. */
var staticGraphs = [{
'apiMethod': 'piwik.getGeographyGraph',
'el': 'graphGeography'
}, {
'apiMethod': 'piwik.getDevicesGraph',
'el': 'graphDevices'
}];
/* Iterates through the objects relating to static graphs and calls them
* to populate page. @todo: Move this to Backbone.js
**/
var loadStaticGraphs = function() {
$.each(staticGraphs, function(index, graph) {
indicoRequest(graph.apiMethod, getIndicoBaseParams(),
function(result, error) {
if (!error) {
$('#' + graph.el).attr('src', result);
} else {
$('#' + graph.el).html($T('No Graph Data Received'));
}
});
});
};
/**
* Initializer to begin the dynamic loading of widgets etc on pageload.
*/
var statsInit = function() {
loadStaticGraphs();
loadVisitorsGraph();
loadTree();
};
statsInit();
});