From: Tom Rees Date: Fri, 17 May 2013 14:19:01 +0000 Subject: [385] Use page_heading helper function consistently X-Git-Url: http://maxious.lambdacomplex.org/git/?p=ckanext-ga-report.git&a=commitdiff&h=98bba88c9027d3198c72d70fc354c3031060e85a --- [385] Use page_heading helper function consistently --- --- a/ckanext/ga_report/controller.py +++ b/ckanext/ga_report/controller.py @@ -191,25 +191,11 @@ q = model.Session.query(GA_Stat).\ filter(GA_Stat.stat_name==k).\ order_by(GA_Stat.period_name) - # Run the query on all months to gather graph data - graph = {} - for stat in q: - graph[ stat.key ] = graph.get(stat.key,{ - 'name':stat.key, - 'data': [] - }) - graph[ stat.key ]['data'].append({ - 'x':_get_unix_epoch(stat.period_name), - 'y':float(stat.value) - }) - setattr(c, v+'_graph', json.dumps( _to_rickshaw(graph.values(),percentageMode=True) )) - # Buffer the tabular data if c.month: entries = [] q = q.filter(GA_Stat.period_name==c.month).\ order_by('ga_stat.value::int desc') - d = collections.defaultdict(int) for e in q.all(): d[e.key] += int(e.value) @@ -218,6 +204,23 @@ entries.append((key,val,)) entries = sorted(entries, key=operator.itemgetter(1), reverse=True) + # Run a query on all months to gather graph data + graph_query = model.Session.query(GA_Stat).\ + filter(GA_Stat.stat_name==k).\ + order_by(GA_Stat.period_name) + graph_dict = {} + for stat in graph_query: + graph_dict[ stat.key ] = graph_dict.get(stat.key,{ + 'name':stat.key, + 'raw': {} + }) + graph_dict[ stat.key ]['raw'][stat.period_name] = float(stat.value) + stats_in_table = [x[0] for x in entries] + stats_not_in_table = set(graph_dict.keys()) - set(stats_in_table) + stats = stats_in_table + sorted(list(stats_not_in_table)) + graph = [graph_dict[x] for x in stats] + setattr(c, v+'_graph', json.dumps( _to_rickshaw(graph,percentageMode=True) )) + # Get the total for each set of values and then set the value as # a percentage of the total if k == 'Social sources': @@ -246,7 +249,7 @@ writer = csv.writer(response) writer.writerow(["Publisher Title", "Publisher Name", "Views", "Visits", "Period Name"]) - top_publishers, top_publishers_graph = _get_top_publishers(None) + top_publishers = _get_top_publishers(limit=None) for publisher,view,visit in top_publishers: writer.writerow([publisher.title.encode('utf-8'), @@ -268,7 +271,7 @@ if not c.publisher: abort(404, 'A publisher with that name could not be found') - packages = self._get_packages(c.publisher) + packages = self._get_packages(publisher=c.publisher, month=c.month) response.headers['Content-Type'] = "text/csv; charset=utf-8" response.headers['Content-Disposition'] = \ str('attachment; filename=datasets_%s_%s.csv' % (c.publisher_name, month,)) @@ -297,15 +300,16 @@ if c.month: c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month]) - c.top_publishers, graph_data = _get_top_publishers() - c.top_publishers_graph = json.dumps( _to_rickshaw(graph_data.values()) ) + c.top_publishers = _get_top_publishers() + graph_data = _get_top_publishers_graph() + c.top_publishers_graph = json.dumps( _to_rickshaw(graph_data) ) return render('ga_report/publisher/index.html') - def _get_packages(self, publisher=None, count=-1): + def _get_packages(self, publisher=None, month='', count=-1): '''Returns the datasets in order of views''' have_download_data = True - month = c.month or 'All' + month = month or 'All' if month != 'All': have_download_data = month >= DOWNLOADS_AVAILABLE_FROM @@ -382,78 +386,71 @@ entry = q.filter(GA_Url.period_name==c.month).first() c.publisher_page_views = entry.pageviews if entry else 0 - c.top_packages = self._get_packages(c.publisher, 20) + c.top_packages = self._get_packages(publisher=c.publisher, count=20, month=c.month) # Graph query - top_package_names = [ x[0].name for x in c.top_packages ] + top_packages_all_time = self._get_packages(publisher=c.publisher, count=20, month='All') + top_package_names = [ x[0].name for x in top_packages_all_time ] graph_query = model.Session.query(GA_Url,model.Package)\ .filter(model.Package.name==GA_Url.package_id)\ .filter(GA_Url.url.like('/dataset/%'))\ .filter(GA_Url.package_id.in_(top_package_names)) - graph_data = {} + all_series = {} for entry,package in graph_query: if not package: continue if entry.period_name=='All': continue - graph_data[package.id] = graph_data.get(package.id,{ + all_series[package.name] = all_series.get(package.name,{ 'name':package.title, - 'data':[] + 'raw': {} }) - graph_data[package.id]['data'].append({ - 'x':_get_unix_epoch(entry.period_name), - 'y':int(entry.pageviews), - }) - - c.graph_data = json.dumps( _to_rickshaw(graph_data.values()) ) + all_series[package.name]['raw'][entry.period_name] = int(entry.pageviews) + graph = [ all_series[series_name] for series_name in top_package_names ] + c.graph_data = json.dumps( _to_rickshaw(graph) ) return render('ga_report/publisher/read.html') def _to_rickshaw(data, percentageMode=False): if data==[]: return data - # Create a consistent x-axis - num_points = [ len(package['data']) for package in data ] - ideal_index = num_points.index( max(num_points) ) - x_axis = [ point['x'] for point in data[ideal_index]['data'] ] - for package in data: - xs = [ point['x'] for point in package['data'] ] - assert set(xs).issubset( set(x_axis) ), (xs, x_axis) - # Zero pad any missing values - for x in set(x_axis).difference(set(xs)): - package['data'].append( {'x':x, 'y':0} ) - assert len(package['data'])==len(x_axis), (len(package['data']),len(x_axis),package['data'],x_axis,set(x_axis).difference(set(xs))) - if percentageMode: - # Transform data into percentage stacks - totals = {} - for x in x_axis: - for package in data: - for point in package['data']: - totals[ point['x'] ] = totals.get(point['x'],0) + point['y'] - # Roll insignificant series into a catch-all - THRESHOLD = 0.01 - significant_series = [] - for package in data: - for point in package['data']: - fraction = float(point['y']) / totals[point['x']] - if fraction>THRESHOLD and not (package in significant_series): - significant_series.append(package) - temp = {} - for package in data: - if package in significant_series: continue - for point in package['data']: - temp[point['x']] = temp.get(point['x'],0) + point['y'] - catch_all = { 'name':'Other','data': [ {'x':x,'y':y} for x,y in temp.items() ] } - # Roll insignificant series into one - data = significant_series - data.append(catch_all) - # Turn each point into a percentage - for package in data: - for point in package['data']: - point['y'] = (point['y']*100) / totals[point['x']] - # Sort the points - for package in data: - package['data'] = sorted( package['data'], key=lambda x:x['x'] ) - # Strip the latest month's incomplete analytics - package['data'] = package['data'][:-1] + # x-axis is every month in c.months. Note that data might not exist + # for entire history, eg. for recently-added datasets + x_axis = [x[0] for x in c.months] + x_axis.reverse() # Ascending order + x_axis = x_axis[:-1] # Remove latest month + totals = {} + for series in data: + series['data'] = [] + for x_string in x_axis: + x = _get_unix_epoch( x_string ) + y = series['raw'].get(x_string,0) + series['data'].append({'x':x,'y':y}) + totals[x] = totals.get(x,0)+y + if not percentageMode: + return data + # Turn all data into percentages + # Roll insignificant series into a catch-all + THRESHOLD = 1 + raw_data = data + data = [] + for series in raw_data: + for point in series['data']: + percentage = (100*float(point['y'])) / totals[point['x']] + if not (series in data) and percentage>THRESHOLD: + data.append(series) + point['y'] = percentage + others = [ x for x in raw_data if not (x in data) ] + if len(others): + data_other = [] + for i in range(len(x_axis)): + x = _get_unix_epoch(x_axis[i]) + y = 0 + for series in others: + y += series['data'][i]['y'] + data_other.append({'x':x,'y':y}) + data.append({ + 'name':'Other', + 'data': data_other + }) return data @@ -478,35 +475,51 @@ top_publishers = [] res = connection.execute(q, month) - department_ids = [] for row in res: g = model.Group.get(row[0]) if g: - department_ids.append(row[0]) top_publishers.append((g, row[1], row[2])) - - graph = {} - if limit is not None: - # Query for a history graph of these publishers - q = model.Session.query( - GA_Url.department_id, - GA_Url.period_name, - func.sum(cast(GA_Url.pageviews,sqlalchemy.types.INT)))\ - .filter( GA_Url.department_id.in_(department_ids) )\ - .filter( GA_Url.period_name!='All' )\ - .filter( GA_Url.url.like('/dataset/%') )\ - .filter( GA_Url.package_id!='' )\ - .group_by( GA_Url.department_id, GA_Url.period_name ) - for dept_id,period_name,views in q: - graph[dept_id] = graph.get( dept_id, { - 'name' : model.Group.get(dept_id).title, - 'data' : [] - }) - graph[dept_id]['data'].append({ - 'x': _get_unix_epoch(period_name), - 'y': views - }) - return top_publishers, graph + return top_publishers + + +def _get_top_publishers_graph(limit=20): + ''' + Returns a list of the top 20 publishers by dataset visits. + (The number to show can be varied with 'limit') + ''' + connection = model.Session.connection() + q = """ + select department_id, sum(pageviews::int) views + from ga_url + where department_id <> '' + and package_id <> '' + and url like '/dataset/%%' + and period_name='All' + group by department_id order by views desc + """ + if limit: + q = q + " limit %s;" % (limit) + + res = connection.execute(q) + department_ids = [ row[0] for row in res ] + + # Query for a history graph of these department ids + q = model.Session.query( + GA_Url.department_id, + GA_Url.period_name, + func.sum(cast(GA_Url.pageviews,sqlalchemy.types.INT)))\ + .filter( GA_Url.department_id.in_(department_ids) )\ + .filter( GA_Url.url.like('/dataset/%') )\ + .filter( GA_Url.package_id!='' )\ + .group_by( GA_Url.department_id, GA_Url.period_name ) + graph_dict = {} + for dept_id,period_name,views in q: + graph_dict[dept_id] = graph_dict.get( dept_id, { + 'name' : model.Group.get(dept_id).title, + 'raw' : {} + }) + graph_dict[dept_id]['raw'][period_name] = views + return [ graph_dict[id] for id in department_ids ] def _get_publishers(): --- a/ckanext/ga_report/helpers.py +++ b/ckanext/ga_report/helpers.py @@ -80,7 +80,7 @@ return base.render_snippet('ga_report/ga_popular_single.html', **context) -def most_popular_datasets(publisher, count=20): +def most_popular_datasets(publisher, count=20, preview_image=None): if not publisher: _log.error("No valid publisher passed to 'most_popular_datasets'") @@ -92,7 +92,8 @@ 'dataset_count': len(results), 'datasets': results, - 'publisher': publisher + 'publisher': publisher, + 'preview_image': preview_image } return base.render_snippet('ga_report/publisher/popular.html', **ctx) @@ -121,3 +122,17 @@ return sorted(results, key=operator.itemgetter(1), reverse=True) +def month_option_title(month_iso, months, day): + month_isos = [ iso_code for (iso_code,name) in months ] + try: + index = month_isos.index(month_iso) + except ValueError: + _log.error('Month "%s" not found in list of months.' % month_iso) + return month_iso + month_name = months[index][1] + if index==0: + return month_name + (' (up to %s)'%day) + return month_name + + + --- a/ckanext/ga_report/plugin.py +++ b/ckanext/ga_report/plugin.py @@ -5,7 +5,8 @@ from ckanext.ga_report.helpers import (most_popular_datasets, popular_datasets, - single_popular_dataset) + single_popular_dataset, + month_option_title) log = logging.getLogger('ckanext.ga-report') @@ -27,7 +28,8 @@ 'ga_report_installed': lambda: True, 'popular_datasets': 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 } def after_map(self, map): --- a/ckanext/ga_report/public/css/ga_report.css +++ b/ckanext/ga_report/public/css/ga_report.css @@ -2,6 +2,11 @@ padding: 1px 0 0 0; width: 108px; text-align: center; + /* Hack to hide the momentary flash of text + * before sparklines are fully rendered */ + font-size: 1px; + color: transparent; + overflow: hidden; } .rickshaw_chart_container { position: relative; @@ -16,16 +21,9 @@ bottom: 0; } .rickshaw_legend { - position: absolute; - right: 0; - top: 0; - margin-left: 15px; - padding: 0 5px; background: transparent; - max-width: 150px; - overflow: hidden; - background: rgba(0,0,0,0.05); - border-radius:5px; + width: 100%; + padding-top: 4px; } .rickshaw_y_axis { position: absolute; @@ -38,4 +36,34 @@ color: #000000 !important; font-weight: normal !important; } +.rickshaw_legend .instructions { + color: #000; + margin-bottom: 6px; +} +.rickshaw_legend .line .action { + display: none; +} +.rickshaw_legend .line .swatch { + display: block; + float: left; +} +.rickshaw_legend .line .label { + display: block; + white-space: normal; + float: left; + width: 200px; +} +.rickshaw_legend .line .label:hover { + text-decoration: underline; +} + +.ga-reports-table .td-numeric { + text-align: center; +} +.ga-reports-heading { + padding-right: 10px; + margin-top: 4px; + float: left; +} + --- a/ckanext/ga_report/public/scripts/ckanext_ga_reports.js +++ b/ckanext/ga_report/public/scripts/ckanext_ga_reports.js @@ -1,12 +1,34 @@ - var CKAN = CKAN || {}; CKAN.GA_Reports = {}; CKAN.GA_Reports.render_rickshaw = function( css_name, data, mode, colorscheme ) { + var graphLegends = $('#graph-legend-container'); + + function renderError(alertClass,alertText,legendText) { + $("#chart_"+css_name) + .html( '
'+alertText+'
') + .closest('.rickshaw_chart_container').css('height',50); + var myLegend = $('
') + .html(legendText) + .appendTo(graphLegends); + } + + if (!Modernizr.svg) { + renderError('','Your browser does not support vector graphics. No graphs can be rendered.','(Graph cannot be rendered)'); + return; + } + if (data.length==0) { + renderError('alert-info','There is not enough data to render a graph.','(No graph available)'); + return + } + var myLegend = $('
').appendTo(graphLegends); + var palette = new Rickshaw.Color.Palette( { scheme: colorscheme } ); $.each(data, function(i, object) { object['color'] = palette.color(); }); + // Rickshaw renders the legend in reverse order... + data.reverse(); var graphElement = document.querySelector("#chart_"+css_name); @@ -16,27 +38,95 @@ series: data , height: 328 }); - var x_axis = new Rickshaw.Graph.Axis.Time( { graph: graph } ); + var x_axis = new Rickshaw.Graph.Axis.Time( { + graph: graph + } ); var y_axis = new Rickshaw.Graph.Axis.Y( { graph: graph, orientation: 'left', tickFormat: Rickshaw.Fixtures.Number.formatKMBT, - element: document.getElementById('y_axis_'+css_name), + element: document.getElementById('y_axis_'+css_name) } ); var legend = new Rickshaw.Graph.Legend( { element: document.querySelector('#legend_'+css_name), graph: graph } ); - var hoverDetail = new Rickshaw.Graph.HoverDetail( { + var shelving = new Rickshaw.Graph.Behavior.Series.Toggle( { graph: graph, - formatter: function(series, x, y) { - var date = '' + new Date(x * 1000).toUTCString() + ''; - var swatch = ''; - var content = swatch + series.name + ": " + parseInt(y) + '
' + date; - return content; - } + legend: legend } ); + myLegend.prepend('
Click on a series below to isolate its graph:
'); graph.render(); }; +CKAN.GA_Reports.bind_sparklines = function() { + /* + * Bind to the 'totals' tab being on screen, when the + * Sparkline graphs should be drawn. + * Note that they cannot be drawn sooner. + */ + var created = false; + $('a[href="#totals"]').on( + 'shown', + function() { + if (!created) { + var sparkOptions = { + enableTagOptions: true, + type: 'line', + width: 100, + height: 26, + chartRangeMin: 0, + spotColor: '', + maxSpotColor: '', + minSpotColor: '', + highlightSpotColor: '#000000', + lineColor: '#3F8E6D', + fillColor: '#B7E66B' + }; + $('.sparkline').sparkline('html',sparkOptions); + created = true; + } + $.sparkline_display_visible(); + } + ); +}; +CKAN.GA_Reports.bind_sidebar = function() { + /* + * Bind to changes in the tab behaviour: + * Show the correct rickshaw graph in the sidebar. + * Not to be called before all graphs load. + */ + $('a[data-toggle="hashtab"]').on( + 'shown', + function(e) { + var href = $(e.target).attr('href'); + var pane = $(href); + if (!pane.length) { console.err('bad href',href); return; } + var legend_name = "none"; + var graph = pane.find('.rickshaw_chart'); + if (graph.length) { + legend_name = graph.attr('id').replace('chart_',''); + } + legend_name = '#legend_'+legend_name; + $('#graph-legend-container > *').hide(); + $('#graph-legend-container .instructions').show(); + $(legend_name).show(); + } + ); + /* The first tab might already have been shown */ + $('li.active > a[data-toggle="hashtab"]').trigger('shown'); +}; + +CKAN.GA_Reports.bind_month_selector = function() { + var handler = function(e) { + var target = $(e.delegateTarget); + var form = target.closest('form'); + var url = form.attr('action')+'?month='+target.val()+window.location.hash; + window.location = url; + }; + var selectors = $('select[name="month"]'); + assert(selectors.length>0); + selectors.bind('change', handler); +}; + --- /dev/null +++ b/ckanext/ga_report/public/scripts/rickshaw_ie7_shim.js @@ -1,1 +1,109 @@ +/* + * Collection of shims to allow d3 and Rickshaw to load, error-free + * (but ultimately unusable) on Internet Explorer 7. The browser's + * API lacks several crucial functions which these libraries depend + * upon to load; we try to hide these errors from the user. + * + * With thanks to Array functions from: + * http://stackoverflow.com/questions/2790001/fixing-javascript-array-functions-in-internet-explorer-indexof-foreach-etc + * + * Use (Modernizr.svg==true) to detect whether it's okay to draw a graph. + */ +'use strict'; +window.Element = window.Element || {'prototype': {}}; +window.CSSStyleDeclaration = window.CSSStyleDeclaration || {'prototype':{}}; + +// Add ECMA262-5 method binding if not supported natively +// +if (!('bind' in Function.prototype)) { + Function.prototype.bind= function(owner) { + var that= this; + if (arguments.length<=1) { + return function() { + return that.apply(owner, arguments); + }; + } else { + var args= Array.prototype.slice.call(arguments, 1); + return function() { + return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments))); + }; + } + }; +} + +// Add ECMA262-5 string trim if not supported natively +// +if (!('trim' in String.prototype)) { + String.prototype.trim= function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }; +} + +// Add ECMA262-5 Array methods if not supported natively +// +if (!('indexOf' in Array.prototype)) { + Array.prototype.indexOf= function(find, i /*opt*/) { + if (i===undefined) i= 0; + if (i<0) i+= this.length; + if (i<0) i= 0; + for (var n= this.length; ithis.length-1) i= this.length-1; + for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */ + if (i in this && this[i]===find) + return i; + return -1; + }; +} +if (!('forEach' in Array.prototype)) { + Array.prototype.forEach= function(action, that /*opt*/) { + for (var i= 0, n= this.length; ithis.window.xMax&&(b=!1),b}return!0},this.onUpdate=function(a){this.updateCallbacks.push(a)},this.registerRenderer=function(a){this._renderers=this._renderers||{},this._renderers[a.name]=a},this.configure=function(a){(a.width||a.height)&&this.setSize(a),Rickshaw.keys(this.defaults).forEach(function(b){this[b]=b in a?a[b]:b in this?this[b]:this.defaults[b]},this),this.setRenderer(a.renderer||this.renderer.name,a)},this.setRenderer=function(a,b){if(!this._renderers[a])throw"couldn't find renderer "+a;this.renderer=this._renderers[a],typeof b=="object"&&this.renderer.configure(b)},this.setSize=function(a){a=a||{};if(typeof window!==undefined)var b=window.getComputedStyle(this.element,null),c=parseInt(b.getPropertyValue("width")),d=parseInt(b.getPropertyValue("height"));this.width=a.width||c||400,this.height=a.height||d||250,this.vis&&this.vis.attr("width",this.width).attr("height",this.height)},this.initialize(a)},Rickshaw.namespace("Rickshaw.Fixtures.Color"),Rickshaw.Fixtures.Color=function(){this.schemes={},this.schemes.spectrum14=["#ecb796","#dc8f70","#b2a470","#92875a","#716c49","#d2ed82","#bbe468","#a1d05d","#e7cbe6","#d8aad6","#a888c2","#9dc2d3","#649eb9","#387aa3"].reverse(),this.schemes.spectrum2000=["#57306f","#514c76","#646583","#738394","#6b9c7d","#84b665","#a7ca50","#bfe746","#e2f528","#fff726","#ecdd00","#d4b11d","#de8800","#de4800","#c91515","#9a0000","#7b0429","#580839","#31082b"],this.schemes.spectrum2001=["#2f243f","#3c2c55","#4a3768","#565270","#6b6b7c","#72957f","#86ad6e","#a1bc5e","#b8d954","#d3e04e","#ccad2a","#cc8412","#c1521d","#ad3821","#8a1010","#681717","#531e1e","#3d1818","#320a1b"],this.schemes.classic9=["#423d4f","#4a6860","#848f39","#a2b73c","#ddcb53","#c5a32f","#7d5836","#963b20","#7c2626","#491d37","#2f254a"].reverse(),this.schemes.httpStatus={503:"#ea5029",502:"#d23f14",500:"#bf3613",410:"#efacea",409:"#e291dc",403:"#f457e8",408:"#e121d2",401:"#b92dae",405:"#f47ceb",404:"#a82a9f",400:"#b263c6",301:"#6fa024",302:"#87c32b",307:"#a0d84c",304:"#28b55c",200:"#1a4f74",206:"#27839f",201:"#52adc9",202:"#7c979f",203:"#a5b8bd",204:"#c1cdd1"},this.schemes.colorwheel=["#b5b6a9","#858772","#785f43","#96557e","#4682b4","#65b9ac","#73c03a","#cb513a"].reverse(),this.schemes.cool=["#5e9d2f","#73c03a","#4682b4","#7bc3b8","#a9884e","#c1b266","#a47493","#c09fb5"],this.schemes.munin=["#00cc00","#0066b3","#ff8000","#ffcc00","#330099","#990099","#ccff00","#ff0000","#808080","#008f00","#00487d","#b35a00","#b38f00","#6b006b","#8fb300","#b30000","#bebebe","#80ff80","#80c9ff","#ffc080","#ffe680","#aa80ff","#ee00cc","#ff8080","#666600","#ffbfff","#00ffcc","#cc6699","#999900"]},Rickshaw.namespace("Rickshaw.Fixtures.RandomData"),Rickshaw.Fixtures.RandomData=function(a){var b;a=a||1;var c=200,d=Math.floor((new Date).getTime()/1e3);this.addData=function(b){var e=Math.random()*100+15+c,f=b[0].length,g=1;b.forEach(function(b){var c=Math.random()*20,h=e/25+g++ +(Math.cos(f*g*11/960)+2)*15+(Math.cos(f/7)+2)*7+(Math.cos(f/17)+2)*1;b.push({x:f*a+d,y:h+c})}),c=e*.85}},Rickshaw.namespace("Rickshaw.Fixtures.Time"),Rickshaw.Fixtures.Time=function(){var a=(new Date).getTimezoneOffset()*60,b=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],this.units=[{name:"decade",seconds:315576e3,formatter:function(a){return parseInt(a.getUTCFullYear()/10)*10}},{name:"year",seconds:31557600,formatter:function(a){return a.getUTCFullYear()}},{name:"month",seconds:2635200,formatter:function(a){return b.months[a.getUTCMonth()]}},{name:"week",seconds:604800,formatter:function(a){return b.formatDate(a)}},{name:"day",seconds:86400,formatter:function(a){return a.getUTCDate()}},{name:"6 hour",seconds:21600,formatter:function(a){return b.formatTime(a)}},{name:"hour",seconds:3600,formatter:function(a){return b.formatTime(a)}},{name:"15 minute",seconds:900,formatter:function(a){return b.formatTime(a)}},{name:"minute",seconds:60,formatter:function(a){return a.getUTCMinutes()}},{name:"15 second",seconds:15,formatter:function(a){return a.getUTCSeconds()+"s"}},{name:"second",seconds:1,formatter:function(a){return a.getUTCSeconds()+"s"}}],this.unit=function(a){return this.units.filter(function(b){return a==b.name}).shift()},this.formatDate=function(a){return a.toUTCString().match(/, (\w+ \w+ \w+)/)[1]},this.formatTime=function(a){return a.toUTCString().match(/(\d+:\d+):/)[1]},this.ceil=function(a,b){if(b.name=="month"){var c=new Date((a+b.seconds-1)*1e3),d=new Date(0);return d.setUTCFullYear(c.getUTCFullYear()),d.setUTCMonth(c.getUTCMonth()),d.setUTCDate(1),d.setUTCHours(0),d.setUTCMinutes(0),d.setUTCSeconds(0),d.setUTCMilliseconds(0),d.getTime()/1e3}if(b.name=="year"){var c=new Date((a+b.seconds-1)*1e3),d=new Date(0);return d.setUTCFullYear(c.getUTCFullYear()),d.setUTCMonth(0),d.setUTCDate(1),d.setUTCHours(0),d.setUTCMinutes(0),d.setUTCSeconds(0),d.setUTCMilliseconds(0),d.getTime()/1e3}return Math.ceil(a/b.seconds)*b.seconds}},Rickshaw.namespace("Rickshaw.Fixtures.Number"),Rickshaw.Fixtures.Number.formatKMBT=function(a){return a>=1e12?a/1e12+"T":a>=1e9?a/1e9+"B":a>=1e6?a/1e6+"M":a>=1e3?a/1e3+"K":a<1&&a>0?a.toFixed(2):a==0?"":a},Rickshaw.Fixtures.Number.formatBase1024KMGTP=function(a){return a>=0x4000000000000?a/0x4000000000000+"P":a>=1099511627776?a/1099511627776+"T":a>=1073741824?a/1073741824+"G":a>=1048576?a/1048576+"M":a>=1024?a/1024+"K":a<1&&a>0?a.toFixed(2):a==0?"":a},Rickshaw.namespace("Rickshaw.Color.Palette"),Rickshaw.Color.Palette=function(a){var b=new Rickshaw.Fixtures.Color;a=a||{},this.schemes={},this.scheme=b.schemes[a.scheme]||a.scheme||b.schemes.colorwheel,this.runningIndex=0,this.generatorIndex=0;if(a.interpolatedStopCount){var c=this.scheme.length-1,d,e,f=[];for(d=0;dc.graph.x.range()[1]){b.element&&(b.line.classList.add("offscreen"),b.element.style.display="none"),b.boxes.forEach(function(a){a.rangeElement&&a.rangeElement.classList.add("offscreen")});return}if(!b.element){var e=b.element=document.createElement("div");e.classList.add("annotation"),this.elements.timeline.appendChild(e),e.addEventListener("click",function(a){e.classList.toggle("active"),b.line.classList.toggle("active"),b.boxes.forEach(function(a){a.rangeElement&&a.rangeElement.classList.toggle("active")})},!1)}b.element.style.left=d+"px",b.element.style.display="block",b.boxes.forEach(function(a){var e=a.element;e||(e=a.element=document.createElement("div"),e.classList.add("content"),e.innerHTML=a.content,b.element.appendChild(e),b.line=document.createElement("div"),b.line.classList.add("annotation_line"),c.graph.element.appendChild(b.line),a.end&&(a.rangeElement=document.createElement("div"),a.rangeElement.classList.add("annotation_range"),c.graph.element.appendChild(a.rangeElement)));if(a.end){var f=d,g=Math.min(c.graph.x(a.end),c.graph.x.range()[1]);f>g&&(g=d,f=Math.max(c.graph.x(a.end),c.graph.x.range()[0]));var h=g-f;a.rangeElement.style.left=f+"px",a.rangeElement.style.width=h+"px",a.rangeElement.classList.remove("offscreen")}b.line.classList.remove("offscreen"),b.line.style.left=d+"px"})},this)},this.graph.onUpdate(function(){c.update()})},Rickshaw.namespace("Rickshaw.Graph.Axis.Time"),Rickshaw.Graph.Axis.Time=function(a){var b=this;this.graph=a.graph,this.elements=[],this.ticksTreatment=a.ticksTreatment||"plain",this.fixedTimeUnit=a.timeUnit;var c=new Rickshaw.Fixtures.Time;this.appropriateTimeUnit=function(){var a,b=c.units,d=this.graph.x.domain(),e=d[1]-d[0];return b.forEach(function(b){Math.floor(e/b.seconds)>=2&&(a=a||b)}),a||c.units[c.units.length-1]},this.tickOffsets=function(){var a=this.graph.x.domain(),b=this.fixedTimeUnit||this.appropriateTimeUnit(),d=Math.ceil((a[1]-a[0])/b.seconds),e=a[0],f=[];for(var g=0;gb.graph.x.range()[1])return;var c=document.createElement("div");c.style.left=b.graph.x(a.value)+"px",c.classList.add("x_tick"),c.classList.add(b.ticksTreatment);var d=document.createElement("div");d.classList.add("title"),d.innerHTML=a.unit.formatter(new Date(a.value*1e3)),c.appendChild(d),b.graph.element.appendChild(c),b.elements.push(c)})},this.graph.onUpdate(function(){b.render()})},Rickshaw.namespace("Rickshaw.Graph.Axis.Y"),Rickshaw.Graph.Axis.Y=function(a){var b=this,c=.1;this.initialize=function(a){this.graph=a.graph,this.orientation=a.orientation||"right";var c=a.pixelsPerTick||75;this.ticks=a.ticks||Math.floor(this.graph.height/c),this.tickSize=a.tickSize||4,this.ticksTreatment=a.ticksTreatment||"plain",a.element?(this.element=a.element,this.vis=d3.select(a.element).append("svg:svg").attr("class","rickshaw_graph y_axis"),this.element=this.vis[0][0],this.element.style.position="relative",this.setSize({width:a.width,height:a.height})):this.vis=this.graph.vis,this.graph.onUpdate(function(){b.render()})},this.setSize=function(a){a=a||{};if(!this.element)return;if(typeof window!="undefined"){var b=window.getComputedStyle(this.element.parentNode,null),d=parseInt(b.getPropertyValue("width"));if(!a.auto)var e=parseInt(b.getPropertyValue("height"))}this.width=a.width||d||this.graph.width*c,this.height=a.height||e||this.graph.height,this.vis.attr("width",this.width).attr("height",this.height*(1+c));var f=this.height*c;this.element.style.top=-1*f+"px"},this.render=function(){this.graph.height!==this._renderHeight&&this.setSize({auto:!0});var b=d3.svg.axis().scale(this.graph.y).orient(this.orientation);b.tickFormat(a.tickFormat||function(a){return a});if(this.orientation=="left")var d=this.height*c,e="translate("+this.width+", "+d+")";this.element&&this.vis.selectAll("*").remove(),this.vis.append("svg:g").attr("class",["y_ticks",this.ticksTreatment].join(" ")).attr("transform",e).call(b.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));var f=(this.orientation=="right"?1:-1)*this.graph.width;this.graph.vis.append("svg:g").attr("class","y_grid").call(b.ticks(this.ticks).tickSubdivide(0).tickSize(f)),this._renderHeight=this.graph.height},this.initialize(a)},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Highlight"),Rickshaw.Graph.Behavior.Series.Highlight=function(a){this.graph=a.graph,this.legend=a.legend;var b=this,c={};this.addHighlightEvents=function(a){a.element.addEventListener("mouseover",function(d){b.legend.lines.forEach(function(b){if(a===b)return;c[b.series.name]=c[b.series.name]||b.series.color,b.series.color=d3.interpolateRgb(b.series.color,d3.rgb("#d8d8d8"))(.8).toString()}),b.graph.update()},!1),a.element.addEventListener("mouseout",function(a){b.legend.lines.forEach(function(a){c[a.series.name]&&(a.series.color=c[a.series.name])}),b.graph.update()},!1)},this.legend&&this.legend.lines.forEach(function(a){b.addHighlightEvents(a)})},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Order"),Rickshaw.Graph.Behavior.Series.Order=function(a){this.graph=a.graph,this.legend=a.legend;var b=this;$(function(){$(b.legend.list).sortable({containment:"parent",tolerance:"pointer",update:function(a,c){var d=[];$(b.legend.list).find("li").each(function(a,b){if(!b.series)return;d.push(b.series)});for(var e=b.graph.series.length-1;e>=0;e--)b.graph.series[e]=d.shift();b.graph.update()}}),$(b.legend.list).disableSelection()}),this.graph.onUpdate(function(){var a=window.getComputedStyle(b.legend.element).height;b.legend.element.style.height=a})},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Toggle"),Rickshaw.Graph.Behavior.Series.Toggle=function(a){this.graph=a.graph,this.legend=a.legend;var b=this;this.addAnchor=function(a){var c=document.createElement("a");c.innerHTML="✔",c.classList.add("action"),a.element.insertBefore(c,a.element.firstChild),c.onclick=function(b){a.series.disabled?(a.series.enable(),a.element.classList.remove("disabled")):(a.series.disable(),a.element.classList.add("disabled"))};var d=a.element.getElementsByTagName("span")[0];d.onclick=function(c){var d=a.series.disabled;if(!d)for(var e=0;ee){j=k;break}f[0][k+1]<=e?k++:k--}var e=f[0][j].x,l=this.xFormatter(e),m=b.x(e),n=0,o=b.series.active().map(function(a){return{order:n++,series:a,name:a.name,value:a.stack[j]}}),p,q=function(a,b){return a.value.y0+a.value.y-(b.value.y0+b.value.y)},r=b.y.magnitude.invert(b.element.offsetHeight-d);o.sort(q).forEach(function(a){a.formattedYValue=this.yFormatter.constructor==Array?this.yFormatter[o.indexOf(a)](a.value.y):this.yFormatter(a.value.y),a.graphX=m,a.graphY=b.y(a.value.y0+a.value.y),r>a.value.y0&&rthis.window.xMax&&(b=!1),b}return!0},this.onUpdate=function(a){this.updateCallbacks.push(a)},this.registerRenderer=function(a){this._renderers=this._renderers||{},this._renderers[a.name]=a},this.configure=function(a){(a.width||a.height)&&this.setSize(a),Rickshaw.keys(this.defaults).forEach(function(b){this[b]=b in a?a[b]:b in this?this[b]:this.defaults[b]},this),this.setRenderer(a.renderer||this.renderer.name,a)},this.setRenderer=function(a,b){if(!this._renderers[a])throw"couldn't find renderer "+a;this.renderer=this._renderers[a],typeof b=="object"&&this.renderer.configure(b)},this.setSize=function(a){a=a||{};if(typeof window!==undefined)var b=window.getComputedStyle(this.element,null),c=parseInt(b.getPropertyValue("width")),d=parseInt(b.getPropertyValue("height"));this.width=a.width||c||400,this.height=a.height||d||250,this.vis&&this.vis.attr("width",this.width).attr("height",this.height)},this.initialize(a)},Rickshaw.namespace("Rickshaw.Fixtures.Color"),Rickshaw.Fixtures.Color=function(){this.schemes={},this.schemes.spectrum14=["#ecb796","#dc8f70","#b2a470","#92875a","#716c49","#d2ed82","#bbe468","#a1d05d","#e7cbe6","#d8aad6","#a888c2","#9dc2d3","#649eb9","#387aa3"].reverse(),this.schemes.spectrum2000=["#57306f","#514c76","#646583","#738394","#6b9c7d","#84b665","#a7ca50","#bfe746","#e2f528","#fff726","#ecdd00","#d4b11d","#de8800","#de4800","#c91515","#9a0000","#7b0429","#580839","#31082b"],this.schemes.spectrum2001=["#2f243f","#3c2c55","#4a3768","#565270","#6b6b7c","#72957f","#86ad6e","#a1bc5e","#b8d954","#d3e04e","#ccad2a","#cc8412","#c1521d","#ad3821","#8a1010","#681717","#531e1e","#3d1818","#320a1b"],this.schemes.classic9=["#423d4f","#4a6860","#848f39","#a2b73c","#ddcb53","#c5a32f","#7d5836","#963b20","#7c2626","#491d37","#2f254a"].reverse(),this.schemes.httpStatus={503:"#ea5029",502:"#d23f14",500:"#bf3613",410:"#efacea",409:"#e291dc",403:"#f457e8",408:"#e121d2",401:"#b92dae",405:"#f47ceb",404:"#a82a9f",400:"#b263c6",301:"#6fa024",302:"#87c32b",307:"#a0d84c",304:"#28b55c",200:"#1a4f74",206:"#27839f",201:"#52adc9",202:"#7c979f",203:"#a5b8bd",204:"#c1cdd1"},this.schemes.colorwheel=["#b5b6a9","#858772","#785f43","#96557e","#4682b4","#65b9ac","#73c03a","#cb513a"].reverse(),this.schemes.cool=["#5e9d2f","#73c03a","#4682b4","#7bc3b8","#a9884e","#c1b266","#a47493","#c09fb5"],this.schemes.munin=["#00cc00","#0066b3","#ff8000","#ffcc00","#330099","#990099","#ccff00","#ff0000","#808080","#008f00","#00487d","#b35a00","#b38f00","#6b006b","#8fb300","#b30000","#bebebe","#80ff80","#80c9ff","#ffc080","#ffe680","#aa80ff","#ee00cc","#ff8080","#666600","#ffbfff","#00ffcc","#cc6699","#999900"]},Rickshaw.namespace("Rickshaw.Fixtures.RandomData"),Rickshaw.Fixtures.RandomData=function(a){var b;a=a||1;var c=200,d=Math.floor((new Date).getTime()/1e3);this.addData=function(b){var e=Math.random()*100+15+c,f=b[0].length,g=1;b.forEach(function(b){var c=Math.random()*20,h=e/25+g++ +(Math.cos(f*g*11/960)+2)*15+(Math.cos(f/7)+2)*7+(Math.cos(f/17)+2)*1;b.push({x:f*a+d,y:h+c})}),c=e*.85}},Rickshaw.namespace("Rickshaw.Fixtures.Time"),Rickshaw.Fixtures.Time=function(){var a=(new Date).getTimezoneOffset()*60,b=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],this.units=[{name:"decade",seconds:315576e3,formatter:function(a){return parseInt(a.getUTCFullYear()/10)*10}},{name:"year",seconds:31557600,formatter:function(a){return a.getUTCFullYear()}},{name:"month",seconds:2635200,formatter:function(a){return b.months[a.getUTCMonth()]}},{name:"week",seconds:604800,formatter:function(a){return b.formatDate(a)}},{name:"day",seconds:86400,formatter:function(a){return a.getUTCDate()}},{name:"6 hour",seconds:21600,formatter:function(a){return b.formatTime(a)}},{name:"hour",seconds:3600,formatter:function(a){return b.formatTime(a)}},{name:"15 minute",seconds:900,formatter:function(a){return b.formatTime(a)}},{name:"minute",seconds:60,formatter:function(a){return a.getUTCMinutes()}},{name:"15 second",seconds:15,formatter:function(a){return a.getUTCSeconds()+"s"}},{name:"second",seconds:1,formatter:function(a){return a.getUTCSeconds()+"s"}}],this.unit=function(a){return this.units.filter(function(b){return a==b.name}).shift()},this.formatDate=function(a){return a.toUTCString().match(/, (\w+ \w+ \w+)/)[1]},this.formatTime=function(a){return a.toUTCString().match(/(\d+:\d+):/)[1]},this.ceil=function(a,b){if(b.name=="month"){var c=new Date((a+b.seconds-1)*1e3),d=new Date(0);return d.setUTCFullYear(c.getUTCFullYear()),d.setUTCMonth(c.getUTCMonth()),d.setUTCDate(1),d.setUTCHours(0),d.setUTCMinutes(0),d.setUTCSeconds(0),d.setUTCMilliseconds(0),d.getTime()/1e3}if(b.name=="year"){var c=new Date((a+b.seconds-1)*1e3),d=new Date(0);return d.setUTCFullYear(c.getUTCFullYear()),d.setUTCMonth(0),d.setUTCDate(1),d.setUTCHours(0),d.setUTCMinutes(0),d.setUTCSeconds(0),d.setUTCMilliseconds(0),d.getTime()/1e3}return Math.ceil(a/b.seconds)*b.seconds}},Rickshaw.namespace("Rickshaw.Fixtures.Number"),Rickshaw.Fixtures.Number.formatKMBT=function(a){return a>=1e12?a/1e12+"T":a>=1e9?a/1e9+"B":a>=1e6?a/1e6+"M":a>=1e3?a/1e3+"K":a<1&&a>0?a.toFixed(2):a==0?"":a},Rickshaw.Fixtures.Number.formatBase1024KMGTP=function(a){return a>=0x4000000000000?a/0x4000000000000+"P":a>=1099511627776?a/1099511627776+"T":a>=1073741824?a/1073741824+"G":a>=1048576?a/1048576+"M":a>=1024?a/1024+"K":a<1&&a>0?a.toFixed(2):a==0?"":a},Rickshaw.namespace("Rickshaw.Color.Palette"),Rickshaw.Color.Palette=function(a){var b=new Rickshaw.Fixtures.Color;a=a||{},this.schemes={},this.scheme=b.schemes[a.scheme]||a.scheme||b.schemes.colorwheel,this.runningIndex=0,this.generatorIndex=0;if(a.interpolatedStopCount){var c=this.scheme.length-1,d,e,f=[];for(d=0;dc.graph.x.range()[1]){b.element&&(b.line.classList.add("offscreen"),b.element.style.display="none"),b.boxes.forEach(function(a){a.rangeElement&&a.rangeElement.classList.add("offscreen")});return}if(!b.element){var e=b.element=document.createElement("div");e.classList.add("annotation"),this.elements.timeline.appendChild(e),e.addEventListener("click",function(a){e.classList.toggle("active"),b.line.classList.toggle("active"),b.boxes.forEach(function(a){a.rangeElement&&a.rangeElement.classList.toggle("active")})},!1)}b.element.style.left=d+"px",b.element.style.display="block",b.boxes.forEach(function(a){var e=a.element;e||(e=a.element=document.createElement("div"),e.classList.add("content"),e.innerHTML=a.content,b.element.appendChild(e),b.line=document.createElement("div"),b.line.classList.add("annotation_line"),c.graph.element.appendChild(b.line),a.end&&(a.rangeElement=document.createElement("div"),a.rangeElement.classList.add("annotation_range"),c.graph.element.appendChild(a.rangeElement)));if(a.end){var f=d,g=Math.min(c.graph.x(a.end),c.graph.x.range()[1]);f>g&&(g=d,f=Math.max(c.graph.x(a.end),c.graph.x.range()[0]));var h=g-f;a.rangeElement.style.left=f+"px",a.rangeElement.style.width=h+"px",a.rangeElement.classList.remove("offscreen")}b.line.classList.remove("offscreen"),b.line.style.left=d+"px"})},this)},this.graph.onUpdate(function(){c.update()})},Rickshaw.namespace("Rickshaw.Graph.Axis.Time"),Rickshaw.Graph.Axis.Time=function(a){var b=this;this.graph=a.graph,this.elements=[],this.ticksTreatment=a.ticksTreatment||"plain",this.fixedTimeUnit=a.timeUnit;var c=new Rickshaw.Fixtures.Time;this.appropriateTimeUnit=function(){var a,b=c.units,d=this.graph.x.domain(),e=d[1]-d[0];return b.forEach(function(b){Math.floor(e/b.seconds)>=2&&(a=a||b)}),a||c.units[c.units.length-1]},this.tickOffsets=function(){var a=this.graph.x.domain(),b=this.fixedTimeUnit||this.appropriateTimeUnit(),d=Math.ceil((a[1]-a[0])/b.seconds),e=a[0],f=[];for(var g=0;gb.graph.x.range()[1])return;var c=document.createElement("div");c.style.left=b.graph.x(a.value)+"px",c.classList.add("x_tick"),c.classList.add(b.ticksTreatment);var d=document.createElement("div");d.classList.add("title"),d.innerHTML=a.unit.formatter(new Date(a.value*1e3)),c.appendChild(d),b.graph.element.appendChild(c),b.elements.push(c)})},this.graph.onUpdate(function(){b.render()})},Rickshaw.namespace("Rickshaw.Graph.Axis.Y"),Rickshaw.Graph.Axis.Y=function(a){var b=this,c=.1;this.initialize=function(a){this.graph=a.graph,this.orientation=a.orientation||"right";var c=a.pixelsPerTick||75;this.ticks=a.ticks||Math.floor(this.graph.height/c),this.tickSize=a.tickSize||4,this.ticksTreatment=a.ticksTreatment||"plain",a.element?(this.element=a.element,this.vis=d3.select(a.element).append("svg:svg").attr("class","rickshaw_graph y_axis"),this.element=this.vis[0][0],this.element.style.position="relative",this.setSize({width:a.width,height:a.height})):this.vis=this.graph.vis,this.graph.onUpdate(function(){b.render()})},this.setSize=function(a){a=a||{};if(!this.element)return;if(typeof window!="undefined"){var b=window.getComputedStyle(this.element.parentNode,null),d=parseInt(b.getPropertyValue("width"));if(!a.auto)var e=parseInt(b.getPropertyValue("height"))}this.width=a.width||d||this.graph.width*c,this.height=a.height||e||this.graph.height,this.vis.attr("width",this.width).attr("height",this.height*(1+c));var f=this.height*c;this.element.style.top=-1*f+"px"},this.render=function(){this.graph.height!==this._renderHeight&&this.setSize({auto:!0});var b=d3.svg.axis().scale(this.graph.y).orient(this.orientation);b.tickFormat(a.tickFormat||function(a){return a});if(this.orientation=="left")var d=this.height*c,e="translate("+this.width+", "+d+")";this.element&&this.vis.selectAll("*").remove(),this.vis.append("svg:g").attr("class",["y_ticks",this.ticksTreatment].join(" ")).attr("transform",e).call(b.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));var f=(this.orientation=="right"?1:-1)*this.graph.width;this.graph.vis.append("svg:g").attr("class","y_grid").call(b.ticks(this.ticks).tickSubdivide(0).tickSize(f)),this._renderHeight=this.graph.height},this.initialize(a)},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Highlight"),Rickshaw.Graph.Behavior.Series.Highlight=function(a){this.graph=a.graph,this.legend=a.legend;var b=this,c={};this.addHighlightEvents=function(a){a.element.addEventListener("mouseover",function(d){b.legend.lines.forEach(function(b){if(a===b)return;c[b.series.name]=c[b.series.name]||b.series.color,b.series.color=d3.interpolateRgb(b.series.color,d3.rgb("#d8d8d8"))(.8).toString()}),b.graph.update()},!1),a.element.addEventListener("mouseout",function(a){b.legend.lines.forEach(function(a){c[a.series.name]&&(a.series.color=c[a.series.name])}),b.graph.update()},!1)},this.legend&&this.legend.lines.forEach(function(a){b.addHighlightEvents(a)})},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Order"),Rickshaw.Graph.Behavior.Series.Order=function(a){this.graph=a.graph,this.legend=a.legend;var b=this;$(function(){$(b.legend.list).sortable({containment:"parent",tolerance:"pointer",update:function(a,c){var d=[];$(b.legend.list).find("li").each(function(a,b){if(!b.series)return;d.push(b.series)});for(var e=b.graph.series.length-1;e>=0;e--)b.graph.series[e]=d.shift();b.graph.update()}}),$(b.legend.list).disableSelection()}),this.graph.onUpdate(function(){var a=window.getComputedStyle(b.legend.element).height;b.legend.element.style.height=a})},Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Toggle"),Rickshaw.Graph.Behavior.Series.Toggle=function(a){this.graph=a.graph,this.legend=a.legend;var b=this;this.addAnchor=function(a){var c=document.createElement("a");c.innerHTML="✔",c.classList.add("action"),a.element.insertBefore(c,a.element.firstChild),c.onclick=function(b){a.series.disabled?(a.series.enable(),a.element.classList.remove("disabled")):(a.series.disable(),a.element.classList.add("disabled"))};var d=a.element.getElementsByTagName("span")[0];d.onclick=function(c){var d=a.series.disabled;if(!d)for(var e=0;ee){j=k;break}f[0][k+1]<=e?k++:k--}var e=f[0][j].x,l=this.xFormatter(e),m=b.x(e),n=0,o=b.series.active().map(function(a){return{order:n++,series:a,name:a.name,value:a.stack[j]}}),p,q=function(a,b){return a.value.y0+a.value.y-(b.value.y0+b.value.y)},r=b.y.magnitude.invert(b.element.offsetHeight-d);o.sort(q).forEach(function(a){a.formattedYValue=this.yFormatter.constructor==Array?this.yFormatter[o.indexOf(a)](a.value.y):this.yFormatter(a.value.y),a.graphX=m,a.graphY=b.y(a.value.y0+a.value.y),r>a.value.y0&&r0?this[0].data.forEach(function(b){a.data.push({x:b.x,y:0})}):a.data.length==0&&a.data.push({x:this.timeBase-(this.timeInterval||0),y:0}),this.push(a),this.legend&&this.legend.addLine(this.itemByName(a.name))},addData:function(a){var b=this.getIndex();Rickshaw.keys(a).forEach(function(a){this.itemByName(a)||this.addItem({name:a})},this),this.forEach(function(c){c.data.push({x:(b*this.timeInterval||1)+this.timeBase,y:a[c.name]||0})},this)},getIndex:function(){return this[0]&&this[0].data&&this[0].data.length?this[0].data.length:0},itemByName:function(a){for(var b=0;b0;d--)this.currentSize+=1,this.currentIndex+=1,this.forEach(function(a){a.data.unshift({x:((d-1)*this.timeInterval||1)+this.timeBase,y:0,i:d})},this)},addData:function($super,a){$super(a),this.currentSize+=1,this.currentIndex+=1;if(this.maxDataPoints!==undefined)while(this.currentSize>this.maxDataPoints)this.dropData()},dropData:function(){this.forEach(function(a){a.data.splice(0,1)}),this.currentSize-=1},getIndex:function(){return this.currentIndex}}); + --- a/ckanext/ga_report/templates/ga_report/ga_util.html +++ b/ckanext/ga_report/templates/ga_report/ga_util.html @@ -8,13 +8,13 @@ - +
@@ -24,7 +24,7 @@ - +
Name Source
${name} ${source}${count}${count}
@@ -34,44 +34,65 @@
-
- +
- + - +
Name% ${title}% ${title}
${name}${value}${value}
-
-
-
-
--- a/ckanext/ga_report/templates/ga_report/notes.html +++ /dev/null @@ -1,16 +1,1 @@ - -
  • -

    Notes

    -
      -
    • "Views" is the number of times a page was loaded in users' browsers.
    • -
    • "Downloads" is the number of times a user has clicked to download either an original or cached resource for a particular dataset. Download information is only available from 2nd December 2012; 'No data' is shown for records before that date.
    • -
    • These usage statistics are confined to users with javascript enabled, which excludes web crawlers and API calls.
    • -
    • The results are not shown when the number of views/visits is tiny. Where these relate to site pages, results are available in full in the CSV download. Where these relate to users' web browser information, results are not disclosed, for privacy reasons.
    • -
    -
  • - - --- a/ckanext/ga_report/templates/ga_report/publisher/index.html +++ b/ckanext/ga_report/templates/ga_report/publisher/index.html @@ -7,71 +7,63 @@ Usage by Publisher + -
  • -

    Download

    -

    - Download as CSV
    -

    -
  • - + ${ga_sidebar(download_link=h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='publisher_csv',month=c.month or 'all'))}
    - - + + + + Site Usage ${usage_nav('Publishers')}
    -

    Site Usage

    - ${usage_nav('Publishers')} +
    + ${rickshaw_graph(c.top_publishers_graph,'publishers')} -
    +
    +
    - - ${month_selector(c.month, c.months, c.day)} - - +

    Statistics for

    + ${month_selector(c.month, c.months, c.day)}
    - ${rickshaw_graph(c.top_publishers_graph,'publishers')} - - - - - +
    PublisherDataset Views
    + + + + - - - - + + + +
    PublisherDataset Views
    - ${h.link_to(publisher.title, h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport', action='read_publisher', id=publisher.name) + (("?month=" + c.month) if c.month else ''))} - ${views}
    + ${h.link_to(publisher.title, h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport', action='read_publisher', id=publisher.name) + (("?month=" + c.month) if c.month else ''))} + ${views}
    - - -
    - - +
    +
    - + --- a/ckanext/ga_report/templates/ga_report/publisher/popular.html +++ b/ckanext/ga_report/templates/ga_report/publisher/popular.html @@ -15,7 +15,12 @@ -

    ${h.link_to("More usage data for " + publisher.title, h.url_for(controller='ckanext.ga_report.controller:GaDatasetReport',action='read_publisher',id=publisher.name))}

    +

    + +
    + More usage data for ${publisher.title} +
    +

    --- a/ckanext/ga_report/templates/ga_report/publisher/read.html +++ b/ckanext/ga_report/templates/ga_report/publisher/read.html @@ -9,30 +9,28 @@ - - + + + -
  • -

    Download

    -

    - Download as CSV
    -

    -
  • - + ${ga_sidebar(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'))}
    - + Site Usage ${usage_nav('Datasets')}
    -

    Site Usage

    - ${usage_nav('Datasets')} +
    +

    ${c.publisher.title}

    + + ${rickshaw_graph(c.graph_data,'dataset-downloads',debug=True)} +
    @@ -47,14 +45,15 @@
    - -

    ${c.publisher.title}

    - -

    No page views in this period

    - + +

    Statistics for ${h.month_option_title(c.month,c.months,c.day)}:

    +
    + +

    Statistics for all months:

    +
    +
    No page views in this period.
    - ${rickshaw_graph(c.graph_data,'dataset-downloads',debug=True)} - +
    @@ -65,13 +64,14 @@ - - + +
    Dataset Views ${h.link_to(package.title or package.name, h.url_for(controller='package', action='read', id=package.name))} ${views}${downloads}${views}${downloads}
    +
    --- a/ckanext/ga_report/templates/ga_report/site/downloads.html +++ b/ckanext/ga_report/templates/ga_report/site/downloads.html @@ -8,19 +8,13 @@ Downloads -
  • -

    Download

    -

    - Download as CSV
    -

    -
  • - - + ${ga_sidebar(download_link=h.url_for(controller='ckanext.ga_report.controller:GaReport',action='csv_downloads',month=c.month or 'all'))}
    + Downloads ${usage_nav('Downloads')}
    -

    Downloads

    - ${usage_nav('Downloads')} + +
    @@ -38,6 +32,7 @@

    No data

    There is no download data available for this month

    +
    --- a/ckanext/ga_report/templates/ga_report/site/index.html +++ b/ckanext/ga_report/templates/ga_report/site/index.html @@ -9,82 +9,70 @@ - - + + + -
  • -

    Download

    -

    - Download as CSV
    -

    -
  • - - + ${ga_sidebar(download_link=h.url_for(controller='ckanext.ga_report.controller:GaReport',action='csv',month=c.month or 'all'))}
    + Site Usage ${usage_nav('Site-wide')} +
    -

    Site Usage

    - ${usage_nav('Site-wide')} - -
    - - ${month_selector(c.month, c.months, c.day)} - - -
    - - +
    - + +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} + +
    - + - +
    NameValueValue History
    ${name}${value}${value} ${','.join([y for x,y in graph])} @@ -96,60 +84,89 @@
    ${rickshaw_graph(c.browser_versions_graph,'browser-versions',mode='stack')} +

    Note: Where a browser has a large number of versions, these have been grouped together.

    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.browser_versions)}
    ${rickshaw_graph(c.browsers_graph,'browsers',mode='stack')} +
    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.browsers)}
    ${rickshaw_graph(c.os_graph,'os',mode='stack')} +
    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.os)}
    ${rickshaw_graph(c.os_versions_graph,'os_versions',mode='stack')} +
    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.os_versions)}

    Number of visits that were referred from social networks

    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${social_table(c.social_referrer_totals)}
    ${rickshaw_graph(c.social_networks_graph, 'social_networks',mode='stack')} +

    Percentage of visits that were referred from these social networks

    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.social_networks, 'Visits')}
    ${rickshaw_graph(c.languages_graph,'languages',mode='stack')} +
    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.languages)}
    ${rickshaw_graph(c.country_graph,'country',mode='stack')} +
    +
    +

    Show stats table for:

    + ${month_selector(c.month, c.months, c.day)} +
    ${stat_table(c.country)}
    +