import logging | import logging |
import ckan.lib.helpers as h | import ckan.lib.helpers as h |
import ckan.plugins as p | import ckan.plugins as p |
from ckan.plugins import implements, toolkit | from ckan.plugins import implements, toolkit |
from ckanext.ga_report.helpers import (most_popular_datasets, | from ckanext.ga_report.helpers import (most_popular_datasets, |
popular_datasets, | popular_datasets, |
single_popular_dataset, | single_popular_dataset, |
month_option_title) | month_option_title) |
log = logging.getLogger('ckanext.ga-report') | log = logging.getLogger('ckanext.ga-report') |
class GAReportPlugin(p.SingletonPlugin): | class GAReportPlugin(p.SingletonPlugin): |
implements(p.IConfigurer, inherit=True) | implements(p.IConfigurer, inherit=True) |
implements(p.IRoutes, inherit=True) | implements(p.IRoutes, inherit=True) |
implements(p.ITemplateHelpers, inherit=True) | implements(p.ITemplateHelpers, inherit=True) |
def update_config(self, config): | def update_config(self, config): |
toolkit.add_template_directory(config, 'templates') | toolkit.add_template_directory(config, 'templates') |
toolkit.add_public_directory(config, 'public') | toolkit.add_public_directory(config, 'public') |
def get_helpers(self): | def get_helpers(self): |
""" | """ |
A dictionary of extra helpers that will be available to provide | A dictionary of extra helpers that will be available to provide |
ga report info to templates. | ga report info to templates. |
""" | """ |
return { | return { |
'ga_report_installed': lambda: True, | 'ga_report_installed': lambda: True, |
'popular_datasets': popular_datasets, | 'popular_datasets': popular_datasets, |
'most_popular_datasets': most_popular_datasets, | 'most_popular_datasets': most_popular_datasets, |
'single_popular_dataset': single_popular_dataset, | 'single_popular_dataset': single_popular_dataset, |
'month_option_title': month_option_title | 'month_option_title': month_option_title |
} | } |
def after_map(self, map): | def after_map(self, map): |
# GaReport | # GaReport |
map.connect( | map.connect( |
'/site-usage', | '/site-usage', |
controller='ckanext.ga_report.controller:GaReport', | controller='ckanext.ga_report.controller:GaReport', |
action='index' | action='index' |
) | ) |
map.connect( | map.connect( |
'/site-usage_{month}.csv', | '/site-usage_{month}.csv', |
controller='ckanext.ga_report.controller:GaReport', | controller='ckanext.ga_report.controller:GaReport', |
action='csv' | action='csv' |
) | ) |
map.connect( | map.connect( |
'/site-usage/downloads', | '/site-usage/downloads', |
controller='ckanext.ga_report.controller:GaReport', | controller='ckanext.ga_report.controller:GaReport', |
action='downloads' | action='downloads' |
) | ) |
map.connect( | map.connect( |
'/site-usage/downloads_{month}.csv', | '/site-usage/downloads_{month}.csv', |
controller='ckanext.ga_report.controller:GaReport', | controller='ckanext.ga_report.controller:GaReport', |
action='csv_downloads' | action='csv_downloads' |
) | ) |
# GaDatasetReport | # GaDatasetReport |
map.connect( | map.connect( |
'/site-usage/publisher', | '/site-usage/publisher', |
controller='ckanext.ga_report.controller:GaDatasetReport', | controller='ckanext.ga_report.controller:GaDatasetReport', |
action='publishers' | action='publishers' |
) | ) |
map.connect( | map.connect( |
'/site-usage/publishers_{month}.csv', | '/site-usage/publishers_{month}.csv', |
controller='ckanext.ga_report.controller:GaDatasetReport', | controller='ckanext.ga_report.controller:GaDatasetReport', |
action='publisher_csv' | action='publisher_csv' |
) | ) |
map.connect( | map.connect( |
'/site-usagesetsets_{id}_{month}.csv', | '/site-usage/dataset/datasets_{id}_{month}.csv', |
controller='ckanext.ga_report.controller:GaDatasetReport', | controller='ckanext.ga_report.controller:GaDatasetReport', |
action='dataset_csv' | action='dataset_csv' |
) | ) |
map.connect( | map.connect( |
'/site-usageset', | '/site-usage/dataset', |
controller='ckanext.ga_report.controller:GaDatasetReport', | controller='ckanext.ga_report.controller:GaDatasetReport', |
action='read' | action='read' |
) | ) |
map.connect( | map.connect( |
'/site-usageset/{id}', | '/site-usage/dataset/{id}', |
controller='ckanext.ga_report.controller:GaDatasetReport', | controller='ckanext.ga_report.controller:GaDatasetReport', |
action='read_publisher' | action='read_publisher' |
) | ) |
return map | return map |
<html xmlns:py="http://genshi.edgewall.org/" | <html xmlns:py="http://genshi.edgewall.org/" |
xmlns:i18n="http://genshi.edgewall.org/i18n" | xmlns:i18n="http://genshi.edgewall.org/i18n" |
xmlns:xi="http://www.w3.org/2001/XInclude" | xmlns:xi="http://www.w3.org/2001/XInclude" |
py:strip=""> | py:strip=""> |
<xi:include href="../ga_util.html" /> | <xi:include href="../ga_util.html" /> |
<py:def function="page_title">Usage by Dataset</py:def> | <py:def function="page_title">Usage by Dataset</py:def> |
<py:def function="optional_head"> | <py:def function="optional_head"> |
<link rel="stylesheet" type="text/css" href="/scripts/vendor/rickshaw.min.css"/> | <link rel="stylesheet" type="text/css" href="/scripts/vendor/rickshaw.min.css"/> |
<link rel="stylesheet" type="text/css" href="/css/ga_report.css?1"/> | <link rel="stylesheet" type="text/css" href="/css/ga_report.css?1"/> |
<script type="text/javascript" src="/scripts/modernizr-2.6.2.custom.js"></script> | <script type="text/javascript" src="/scripts/modernizr-2.6.2.custom.js"></script> |
<script type="text/javascript" src="/scripts/ckanext_ga_reports.js?1"></script> | <script type="text/javascript" src="/scripts/ckanext_ga_reports.js?1"></script> |
<script type="text/javascript" src="/scripts/vendor/jquery.sparkline.modified.js"></script> | <script type="text/javascript" src="/scripts/vendor/jquery.sparkline.modified.js"></script> |
<script type="text/javascript" src="/scripts/rickshaw_ie7_shim.js"></script> | <script type="text/javascript" src="/scripts/rickshaw_ie7_shim.js"></script> |
<script type="text/javascript" src="/scripts/vendor/d3.v2.js"></script> | <script type="text/javascript" src="/scripts/vendor/d3.v2.js"></script> |
<script type="text/javascript" src="/scripts/vendor/d3.layout.min.js"></script> | <script type="text/javascript" src="/scripts/vendor/d3.layout.min.js"></script> |
<script type="text/javascript" src="/scripts/vendor/rickshaw.min.js"></script> | <script type="text/javascript" src="/scripts/vendor/rickshaw.min.js"></script> |
</py:def> | </py:def> |
<py:match path="breadcrumbs"> | <py:match path="breadcrumbs"> |
<li><a href="/site-usage">Site Analytics</a></li> | <li><a href="/site-usage">Site Analytics</a></li> |
<py:if test="c.publisher"> | <py:if test="c.publisher"> |
<li><a href="/site-usage/publisher">Publishers</a></li> | <li><a href="/site-usage/publisher">Publishers</a></li> |
<li py:if="c.publisher"><a href="/site-usage/publisher/${c.publisher.name}">${c.publisher.title}</a></li> | <li py:if="c.publisher"><a href="/site-usage/publisher/${c.publisher.name}">${c.publisher.title}</a></li> |
</py:if> | </py:if> |
<py:if test="not c.publisher"> | <py:if test="not c.publisher"> |
<li><a href="${request.url}">Usage By Dataset</a></li> | <li><a href="${request.url}">Usage By Dataset</a></li> |
</py:if> | </py:if> |
</py:match> | </py:match> |
<div py:match="content"> | <div py:match="content"> |
<py:with vars="download_link=h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='dataset_csv',id=c.publisher_name or 'all',month=c.month or 'all')"> | <py:with vars="download_link=h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='dataset_csv',id=c.publisher_name or 'all',month=c.month or 'all')"> |
<a class="btn button btn-primary btn-sm pull-right" href="${download_link}"><i class="icon-download"></i> Download as CSV</a> | <a class="btn button btn-primary btn-sm pull-right" href="${download_link}"><i class="icon-download"></i> Download as CSV</a> |
</py:with> | </py:with> |
<h1>Site Usage | <h1>Site Usage |
<small py:if="c.publisher">${c.publisher.title}</small> | <small py:if="c.publisher">${c.publisher.title}</small> |
<small py:if="not c.publisher">All datasets</small> | <small py:if="not c.publisher">All datasets</small> |
</h1> | </h1> |
<div class="row" style="background: #fff;"> | <div class="row" style="background: #fff;"> |
<div class="col-md-8"> | <div class="col-md-8"> |
<div class="whitebox"> | <div class="whitebox"> |
<py:if test="c.graph_data"> | <py:if test="c.graph_data"> |
${rickshaw_graph(c.graph_data,'dataset-downloads',debug=True)} | ${rickshaw_graph(c.graph_data,'dataset-downloads',debug=True)} |
</py:if> | </py:if> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
<hr/> | <hr/> |
<py:if test="c.month"> | <py:if test="c.month"> |
<h4>Statistics for ${h.month_option_title(c.month,c.months,c.day)}:</h4> | <h4>Statistics for ${h.month_option_title(c.month,c.months,c.day)}:</h4> |
</py:if> | </py:if> |
<py:if test="not c.month"> | <py:if test="not c.month"> |
<h2>Statistics for all months</h2> | <h2>Statistics for all months</h2> |
</py:if> | </py:if> |
<form style="margin-bottom:10px;" class="form-inline" action="${h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='read')}" method="get"> | <form style="margin-bottom:10px;" class="form-inline" action="${h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='read')}" method="get"> |
<div class="controls"> | <div class="controls"> |
${month_selector(c.month, c.months, c.day)} | ${month_selector(c.month, c.months, c.day)} |
<select name="publisher"> | <select name="publisher"> |
<option value='' py:attrs="{'selected': 'selected' if not c.publisher else None}">All publishers</option> | <option value='' py:attrs="{'selected': 'selected' if not c.publisher else None}">All publishers</option> |
<py:for each="val,desc in c.publishers"> | <py:for each="val,desc in c.publishers"> |
<option value='${val}' py:attrs="{'selected': 'selected' if c.publisher_name == val else None}">${desc}</option> | <option value='${val}' py:attrs="{'selected': 'selected' if c.publisher_name == val else None}">${desc}</option> |
</py:for> | </py:for> |
</select> | </select> |
<input class="btn button btn-primary btn-xs" type='submit' value="Update"/> | <input class="btn button btn-primary btn-xs" type='submit' value="Update"/> |
</div> | </div> |
</form> | </form> |
<div class="alert alert-info" py:if="not c.top_packages">No page views in this period.</div> | <div class="alert alert-info" py:if="not c.top_packages">No page views in this period.</div> |
<py:if test="c.top_packages"> | <py:if test="c.top_packages"> |
<table class="ga-reports-table table table-condensed table-bordered"> | <table class="ga-reports-table table table-condensed table-bordered"> |
<tr> | <tr> |
<th>Dataset</th> | <th>Dataset</th> |
<th>Views</th> | <th>Views</th> |
<th>Downloads</th> | <th>Downloads</th> |
</tr> | </tr> |
<py:for each="package, views, visits,downloads in c.top_packages"> | <py:for each="package, views, visits,downloads in c.top_packages"> |
<tr> | <tr> |
<td> | <td> |
${h.link_to(package.title or package.name, h.url_for(controller='package', action='read', id=package.name))} | ${h.link_to(package.title or package.name, h.url_for(controller='package', action='read', id=package.name))} |
</td> | </td> |
<td class="td-numeric">${views}</td> | <td class="td-numeric">${views}</td> |
<td class="td-numeric">${downloads}</td> | <td class="td-numeric">${downloads}</td> |
</tr> | </tr> |
</py:for> | </py:for> |
</table> | </table> |
</py:if> | </py:if> |
${ga_footer()} | ${ga_footer()} |
</div> | </div> |
<xi:include href="../site/layout.html" /> | <xi:include href="../site/layout.html" /> |
</html> | </html> |
<html xmlns:py="http://genshi.edgewall.org/" | <html xmlns:py="http://genshi.edgewall.org/" |
xmlns:i18n="http://genshi.edgewall.org/i18n" | xmlns:i18n="http://genshi.edgewall.org/i18n" |
xmlns:xi="http://www.w3.org/2001/XInclude" | xmlns:xi="http://www.w3.org/2001/XInclude" |
py:strip=""> | py:strip=""> |
<xi:include href="../ga_util.html" /> | <xi:include href="../ga_util.html" /> |
<py:def function="page_title">Site usage</py:def> | <py:def function="page_title">Site usage</py:def> |
<py:def function="optional_head"> | <py:def function="optional_head"> |
</py:def> | </py:def> |
<py:match path="breadcrumbs"> | <py:match path="breadcrumbs"> |
<li><a href="/site-usage">Site Analytics</a></li> | <li><a href="/site-usage">Site Analytics</a></li> |
<li><a href="/site-usage">Site-wide</a></li> | <li><a href="/site-usage">Site-wide</a></li> |
</py:match> | </py:match> |
<div py:match="content"> | <div py:match="content"> |
<div class="row"> | <div class="row"> |
<div class="col-sm-7 col-md-8 col-lg-9"> | <div class="col-sm-7 col-md-8 col-lg-9"> |
<py:with vars="download_link=h.url_for(controller='ckanext.ga_report.controller:GaReport',action='csv',month=c.month or 'all')"> | <py:with vars="download_link=h.url_for(controller='ckanext.ga_report.controller:GaReport',action='csv',month=c.month or 'all')"> |
<a class="btn button btn-primary btn-sm pull-right" href="${download_link}"><i class="icon-download"></i> Download as CSV</a> | <a class="btn button btn-primary btn-sm pull-right" href="${download_link}"><i class="icon-download"></i> Download as CSV</a> |
</py:with> | </py:with> |
<h1>Site Usage</h1> | <h1>Site Usage</h1> |
</div> | </div> |
<div class="col-sm-5 col-md-4 col-lg-3"> | <div class="col-sm-5 col-md-4 col-lg-3"> |
<div class="panel panel-default"> | <div class="panel panel-default"> |
<div class="panel-heading"><strong>Jump To...</strong></div> | <div class="panel-heading"><strong>Jump To...</strong></div> |
<div class="panel-body"> | <div class="panel-body"> |
<ul> | <ul> |
<li><a href="/site-usage/publisher">Publisher Usage Statistics</a></li> | <li><a href="/site-usage/publisher">Publisher Usage Statistics</a></li> |
<li><a href="/site-usageset">Dataset Usage Statistics</a></li> | <li><a href="/site-usage/dataset">Dataset Usage Statistics</a></li> |
</ul> | </ul> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
<div class="row" style="background: #fff;"> | <div class="row" style="background: #fff;"> |
<div class="col-md-8"> | <div class="col-md-8"> |
<div class="whitebox"> | <div class="whitebox"> |
<div class="tabbable"> | <div class="tabbable"> |
<ul class="nav nav-tabs"> | <ul class="nav nav-tabs"> |
<li class="active"><a href="#totals" data-hash="totals" data-toggle="tab">Totals</a></li> | <li class="active"><a href="#totals" data-hash="totals" data-toggle="tab">Totals</a></li> |
<li class="dropdown"> | <li class="dropdown"> |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Browsers | <a href="#" class="dropdown-toggle" data-toggle="dropdown">Browsers |
<b class="caret"></b></a> | <b class="caret"></b></a> |
<ul class="dropdown-menu"> | <ul class="dropdown-menu"> |
<li><a href="#browsers_names" data-hash="browsers_names" data-toggle="tab">Browsers</a></li> | <li><a href="#browsers_names" data-hash="browsers_names" data-toggle="tab">Browsers</a></li> |
<li><a href="#browsers_versions" data-hash="browsers_versions" data-toggle="tab">Versions</a></li> | <li><a href="#browsers_versions" data-hash="browsers_versions" data-toggle="tab">Versions</a></li> |
</ul> | </ul> |
</li> | </li> |
<li class="dropdown"> | <li class="dropdown"> |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Operating Systems | <a href="#" class="dropdown-toggle" data-toggle="dropdown">Operating Systems |
<b class="caret"></b></a> | <b class="caret"></b></a> |
<ul class="dropdown-menu"> | <ul class="dropdown-menu"> |
<li><a href="#os" data-hash="os" data-toggle="tab">Operating Systems</a></li> | <li><a href="#os" data-hash="os" data-toggle="tab">Operating Systems</a></li> |
<li><a href="#os_versions" data-hash="os_versions" data-toggle="tab">Versions</a></li> | <li><a href="#os_versions" data-hash="os_versions" data-toggle="tab">Versions</a></li> |
</ul> | </ul> |
</li> | </li> |
<li class="dropdown"> | <li class="dropdown"> |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Social | <a href="#" class="dropdown-toggle" data-toggle="dropdown">Social |
<b class="caret"></b></a> | <b class="caret"></b></a> |
<ul class="dropdown-menu"> | <ul class="dropdown-menu"> |
<li><a href="#social_networks" data-hash="social_networks" data-toggle="tab">All networks</a></li> | <li><a href="#social_networks" data-hash="social_networks" data-toggle="tab">All networks</a></li> |
<li><a href="#social_referrals_totals" data-hash="social_referrals_totals" data-toggle="tab">Referral links</a></li> | <li><a href="#social_referrals_totals" data-hash="social_referrals_totals" data-toggle="tab">Referral links</a></li> |
</ul> | </ul> |
</li> | </li> |
<li><a href="#languages" data-hash="languages" data-toggle="tab">Languages</a></li> | <li><a href="#languages" data-hash="languages" data-toggle="tab">Languages</a></li> |
<li><a href="#country" data-hash="country" data-toggle="tab">Country</a></li> | <li><a href="#country" data-hash="country" data-toggle="tab">Country</a></li> |
</ul> | </ul> |
<div class="tab-content"> | <div class="tab-content"> |
<div class="tab-pane active" id="totals"> | <div class="tab-pane active" id="totals"> |
<form class="form-inline" action="${h.url_for(controller='ckanext.ga_report.controller:GaReport',action='index')}" method="get"> | <form class="form-inline" action="${h.url_for(controller='ckanext.ga_report.controller:GaReport',action='index')}" method="get"> |
<h4 class="ga-reports-heading">Show stats table for:</h4> | <h4 class="ga-reports-heading">Show stats table for:</h4> |
${month_selector(c.month, c.months, c.day)} | ${month_selector(c.month, c.months, c.day)} |
</form> | </form> |
<table class="ga-reports-table table table-condensed table-bordered table-striped"> | <table class="ga-reports-table table table-condensed table-bordered table-striped"> |
<tr> | <tr> |
<th>Name</th> | <th>Name</th> |
<th class="td-numeric">Value</th> | <th class="td-numeric">Value</th> |
<th>History</th> | <th>History</th> |
</tr> | </tr> |
<py:for each="name, value, graph in c.global_totals"> | <py:for each="name, value, graph in c.global_totals"> |
<tr> | <tr> |
<td>${name}</td> | <td>${name}</td> |
<td class="td-numeric">${value}</td> | <td class="td-numeric">${value}</td> |
<td class="sparkline-cell"> | <td class="sparkline-cell"> |
<span class="sparkline" sparkTooltips="${','.join([x for x,y in graph])}"> | <span class="sparkline" sparkTooltips="${','.join([x for x,y in graph])}"> |
${','.join([y for x,y in graph])} | ${','.join([y for x,y in graph])} |
</span> |