| # empty file needed for pylons to find templates in this directory | |
Binary files /dev/null and b/ckanext/dga-stats/__init__.pyc differ
| import ckan.plugins as p | |
| from ckan.lib.base import BaseController, config | |
| import stats as stats_lib | |
| import ckan.lib.helpers as h | |
| class StatsController(BaseController): | |
| def index(self): | |
| c = p.toolkit.c | |
| stats = stats_lib.Stats() | |
| rev_stats = stats_lib.RevisionStats() | |
| c.top_rated_packages = stats.top_rated_packages() | |
| c.most_edited_packages = stats.most_edited_packages() | |
| c.largest_groups = stats.largest_groups() | |
| c.top_tags = stats.top_tags() | |
| c.top_package_owners = stats.top_package_owners() | |
| c.new_packages_by_week = rev_stats.get_by_week('new_packages') | |
| c.deleted_packages_by_week = rev_stats.get_by_week('deleted_packages') | |
| c.num_packages_by_week = rev_stats.get_num_packages_by_week() | |
| c.package_revisions_by_week = rev_stats.get_by_week('package_revisions') | |
| # Used in the legacy CKAN templates. | |
| c.packages_by_week = [] | |
| # Used in new CKAN templates gives more control to the templates for formatting. | |
| c.raw_packages_by_week = [] | |
| for week_date, num_packages, cumulative_num_packages in c.num_packages_by_week: | |
| c.packages_by_week.append('[new Date(%s), %s]' % (week_date.replace('-', ','), cumulative_num_packages)) | |
| c.raw_packages_by_week.append({'date': h.date_str_to_datetime(week_date), 'total_packages': cumulative_num_packages}) | |
| c.all_package_revisions = [] | |
| c.raw_all_package_revisions = [] | |
| for week_date, revs, num_revisions, cumulative_num_revisions in c.package_revisions_by_week: | |
| c.all_package_revisions.append('[new Date(%s), %s]' % (week_date.replace('-', ','), num_revisions)) | |
| c.raw_all_package_revisions.append({'date': h.date_str_to_datetime(week_date), 'total_revisions': num_revisions}) | |
| c.new_datasets = [] | |
| c.raw_new_datasets = [] | |
| for week_date, pkgs, num_packages, cumulative_num_packages in c.new_packages_by_week: | |
| c.new_datasets.append('[new Date(%s), %s]' % (week_date.replace('-', ','), num_packages)) | |
| c.raw_new_datasets.append({'date': h.date_str_to_datetime(week_date), 'new_packages': num_packages}) | |
| return p.toolkit.render('ckanext/stats/index.html') | |
| def leaderboard(self, id=None): | |
| c = p.toolkit.c | |
| c.solr_core_url = config.get('ckanext.stats.solr_core_url', | |
| 'http://solr.okfn.org/solr/ckan') | |
| return p.toolkit.render('ckanext/stats/leaderboard.html') | |
| from logging import getLogger | |
| import ckan.plugins as p | |
| log = getLogger(__name__) | |
| class StatsPlugin(p.SingletonPlugin): | |
| '''Stats plugin.''' | |
| p.implements(p.IRoutes, inherit=True) | |
| p.implements(p.IConfigurer, inherit=True) | |
| def after_map(self, map): | |
| map.connect('stats', '/stats', | |
| controller='ckanext.stats.controller:StatsController', | |
| action='index') | |
| map.connect('stats_action', '/stats/{action}', | |
| controller='ckanext.stats.controller:StatsController') | |
| return map | |
| def update_config(self, config): | |
| templates = 'templates' | |
| if p.toolkit.asbool(config.get('ckan.legacy_templates', False)): | |
| templates = 'templates_legacy' | |
| p.toolkit.add_template_directory(config, templates) | |
| p.toolkit.add_public_directory(config, 'public') | |
| p.toolkit.add_resource('public/ckanext/stats', 'ckanext_stats') | |
Binary files /dev/null and b/ckanext/dga-stats/plugin.pyc differ
| **.min.js | |
| **.min.css | |
| # this is a namespace package | |
| try: | |
| import pkg_resources | |
| pkg_resources.declare_namespace(__name__) | |
| except ImportError: | |
| import pkgutil | |
| __path__ = pkgutil.extend_path(__path__, __name__) | |
| # this is a namespace package | |
| try: | |
| import pkg_resources | |
| pkg_resources.declare_namespace(__name__) | |
| except ImportError: | |
| import pkgutil | |
| __path__ = pkgutil.extend_path(__path__, __name__) | |
| # this is a namespace package | |
| try: | |
| import pkg_resources | |
| pkg_resources.declare_namespace(__name__) | |
| except ImportError: | |
| import pkgutil | |
| __path__ = pkgutil.extend_path(__path__, __name__) | |
| jQuery(document).ready(function($) { | |
| $('form').submit(function(e) { | |
| e.preventDefault(); | |
| attribute = $('#form-attribute').val(); | |
| loadSolr(attribute); | |
| }) | |
| // default! (also in html) | |
| loadSolr('tags'); | |
| function loadSolr(attribute) { | |
| var url = solrCoreUrl + '/select?indent=on&wt=json&facet=true&rows=0&indent=true&facet.mincount=1&facet.limit=30&q=*:*&facet.field=' + attribute; | |
| function handleSolr(data) { | |
| var results = []; | |
| ourdata = data.facet_counts.facet_fields[attribute]; | |
| var newrow = {}; | |
| for (ii in ourdata) { | |
| if (ii % 2 == 0) { | |
| newrow.name = ourdata[ii]; | |
| if (!newrow.name) { | |
| newrow.name = '[Not Specified]'; | |
| } | |
| } else { | |
| newrow.count = ourdata[ii]; | |
| results.push(newrow); | |
| newrow = {}; | |
| } | |
| } | |
| display(results); | |
| } | |
| $.ajax({ | |
| url: url, | |
| success: handleSolr, | |
| dataType: 'jsonp', | |
| jsonp: 'json.wrf' | |
| }); | |
| } | |
| function display(results) { | |
| var list = $('#category-counts'); | |
| list.html(''); | |
| if (results.length == 0) { | |
| return | |
| } | |
| var maximum = results[0]['count']; | |
| for(ii in results) { | |
| maximum = Math.max(maximum, results[ii]['count']); | |
| } | |
| $.each(results, function(idx, row) { | |
| var newentry = $('<li></li>'); | |
| newentry.append($('<a href="#">' + row['name'] + '</a>')); | |
| newentry.append($('<span class="count">' + row['count'] + '</a>')); | |
| var percent = 100 * row['count'] / maximum; | |
| newentry.append($('<span class="index" style="width: ' + percent + '%"></span>')); | |
| list.append(newentry); | |
| }); | |
| } | |
| }); | |
| .tab-content h2 { | |
| margin-bottom: 12px; | |
| } | |
| .js .tab-content { | |
| padding-top: 20px; | |
| padding-bottom: 20px; | |
| margin-top: 0; | |
| } | |
| .module-plot-canvas { | |
| display: block; | |
| width: 650px; | |
| height: 300px; | |
| margin: 20px 0; | |
| } | |
| <html> | |
| <head> | |
| <script type="text/javascript"> | |
| var solrCoreUrl = 'http://solr.okfn.org/solr/ckan'; | |
| </script> | |
| <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> | |
| <script type="text/javascript" src="app.js"></script> | |
| <link type="text/css" rel="stylesheet" media="all" href="style.css" /> | |
| </head> | |
| <body> | |
| <h1>CKAN Dataset Leaderboard</h1> | |
| <p>Choose a dataset attribute and find out which categories in that area have the most datasets. E.g. tags, groups, license, res_format, country.</p> | |
| <form> | |
| <label for="category">Choose area</label> | |
| <input type="text" value="tags" name="attribute" id="form-attribute" /> | |
| <input type="submit" value="Dataset Counts »" name="submit" /> | |
| </form> | |
| <div class="category-counts"> | |
| <ul class="chartlist" id="category-counts"> | |
| </ul> | |
| </div> | |
| </body> | |
| </html> | |
| /* A quick module for generating flot charts from an HTML table. Options can | |
| * be passed directly to flot using the data-module-* attributes. The tables | |
| * are currently expected to be marked up as follows: | |
| * | |
| * <table data-module="plot"> | |
| * <thead> | |
| * <tr> | |
| * <th>X Axis</th> | |
| * <th>Series A Legend</th> | |
| * <th>Series B Legend</th> | |
| * </tr> | |
| * </thead> | |
| * <tbody> | |
| * <tr> | |
| * <th>X Value</th> | |
| * <td>Series A Y Value</td> | |
| * <td>Series B Y Value</td> | |
| * </tr> | |
| * ... | |
| * </tbody> | |
| * </table> | |
| * | |
| * Points are pulled out of the th/td elements using innerHTML or by looking | |
| * for a data-value attribute. This is useful when a more readable value | |
| * needs to be used in the elements contents (eg. dates). A data-type attribute | |
| * can also be applied to parse the value. Only data-type="date" is currently | |
| * supported and expects data-value to be a unix timestamp. | |
| */ | |
| this.ckan.module('plot', function (jQuery, _) { | |
| return { | |
| /* Holds the jQuery.plot() object when created */ | |
| graph: null, | |
| /* Holds the canvas container when created */ | |
| canvas: null, | |
| /* Default options */ | |
| options: { | |
| xaxis: {}, | |
| yaxis: {}, | |
| legend: {position: 'nw'}, | |
| colors: ['#ffcc33', '#ff8844'] | |
| }, | |
| /* Sets up the canvas element and parses the table. | |
| * | |
| * Returns nothing. | |
| */ | |
| initialize: function () { | |
| jQuery.proxyAll(this, /_on/); | |
| if (!this.el.is('table')) { | |
| throw new Error('CKAN module plot can only be called on table elements'); | |
| } | |
| this.setupCanvas(); | |
| // Because the canvas doesn't render correctly unless visible we must | |
| // listen for events that reveal the canvas and then try and re-render. | |
| // Currently the most common of these is the "shown" event triggered by | |
| // the tabs plugin. | |
| this.sandbox.body.on("shown", this._onShown); | |
| this.data = this.parseTable(this.el); | |
| this.draw(); | |
| }, | |
| /* Removes event handlers when the module is removed from the DOM. | |
| * | |
| * Returns nothing. | |
| */ | |
| teardown: function () { | |
| this.sandbox.body.off("shown", this._onShown); | |
| }, | |
| /* Creates the canvas wrapper and removes the table from the document. | |
| * | |
| * Returns nothing. | |
| */ | |
| setupCanvas: function () { | |
| this.canvas = jQuery('<div class="module-plot-canvas">'); | |
| this.el.replaceWith(this.canvas); | |
| }, | |
| /* Attempts to draw the chart if the canvas is visible. If not visible the | |
| * graph does not render correctly. So we keep trying until it is. | |
| * | |
| * Examples | |
| * | |
| * module.draw(); | |
| * | |
| * Returns nothing. | |
| */ | |
| draw: function () { | |
| if (!this.drawn && this.canvas.is(':visible')) { | |
| this.graph = jQuery.plot(this.canvas, this.data, this.options); | |
| } | |
| }, | |
| /* Parses an HTML table element to build the data array for the chart. | |
| * The thead element provides the axis and labels for the series. The | |
| * first column in the tbody is used for the x-axis and subsequent | |
| * columns are the series. | |
| * | |
| * table - A table element to parse. | |
| * | |
| * Examples | |
| * | |
| * module.parseTable(module.el); | |
| * | |
| * Returns data object suitable for use in jQuery.plot(). | |
| */ | |
| parseTable: function (table) { | |
| var data = []; | |
| var _this = this; | |
| var headings = table.find('thead tr:first th').map(function () { | |
| return this.innerHTML; | |
| }); | |
| table.find('tbody tr').each(function (row) { | |
| var element = jQuery(this); | |
| var x = []; | |