From 017dc7bf94dfbab845eed7a86d3e7b93a7260135 Mon Sep 17 00:00:00 2001 From: Mike Terzo Date: Mon, 30 Jan 2017 12:24:58 -0500 Subject: [PATCH 1/9] Update node reports table. Disable search which is does not provide any real functionality since you can't search for unchanged, noop or changed, nor and can you filter on since the data is in UTC. Moved the page type to simple which only shows and buttons. Having here makes the tab to wide causing overlay onto the next column. --- puppetboard/templates/node.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/puppetboard/templates/node.html b/puppetboard/templates/node.html index c35e150..9b7964d 100644 --- a/puppetboard/templates/node.html +++ b/puppetboard/templates/node.html @@ -13,7 +13,11 @@ {% endblock script %} {% endblock head %} {% block onload_script %} -{{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, columns=columns) }} +{% macro extra_options(caller) %} + 'pagingType': 'simple', + "bFilter": false, +{% endmacro %} +{{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, columns=columns, extra_options=extra_options) }} {% endblock onload_script %} {% block content %} From 11705775259cd857ef3d21732fa97e6b370c32a2 Mon Sep 17 00:00:00 2001 From: Mike Terzo Date: Tue, 31 Jan 2017 02:39:02 -0500 Subject: [PATCH 2/9] Fix broken sort and filter. Not everything has been migrated to data tables and still needs to be able to sort and filtered. --- .../jquery.tablesort.min.js | 6 +++ puppetboard/static/js/tables.js | 35 ++++++++++++++++ puppetboard/templates/_macros.html | 33 --------------- puppetboard/templates/fact.html | 42 +++++++++++++++++-- puppetboard/templates/index.html | 1 + puppetboard/templates/layout.html | 10 ++++- 6 files changed, 89 insertions(+), 38 deletions(-) create mode 100644 puppetboard/static/jquery-tablesort-v.0.0.7/jquery.tablesort.min.js create mode 100644 puppetboard/static/js/tables.js diff --git a/puppetboard/static/jquery-tablesort-v.0.0.7/jquery.tablesort.min.js b/puppetboard/static/jquery-tablesort-v.0.0.7/jquery.tablesort.min.js new file mode 100644 index 0000000..d9b4041 --- /dev/null +++ b/puppetboard/static/jquery-tablesort-v.0.0.7/jquery.tablesort.min.js @@ -0,0 +1,6 @@ +/* + A simple, lightweight jQuery plugin for creating sortable tables. + https://github.com/kylefox/jquery-tablesort + Version 0.0.7 +*/ +!function(t){t.tablesort=function(e,s){var i=this;this.$table=e,this.$thead=this.$table.find("thead"),this.settings=t.extend({},t.tablesort.defaults,s),this.$sortCells=this.$thead.length>0?this.$thead.find("th:not(.no-sort)"):this.$table.find("th:not(.no-sort)"),this.$sortCells.bind("click.tablesort",function(){i.sort(t(this))}),this.index=null,this.$th=null,this.direction=null},t.tablesort.prototype={sort:function(e,s){var i=new Date,n=this,o=this.$table,l=this.$thead.length>0?o.find("tbody tr"):o.find("tr").has("td"),a=o.find("tr td:nth-of-type("+(e.index()+1)+")"),r=e.data().sortBy,d=[],h=a.map(function(s,i){return r?"function"==typeof r?r(t(e),t(i),n):r:null!=t(this).data().sortValue?t(this).data().sortValue:t(this).text()});0!==h.length&&("asc"!==s&&"desc"!==s?this.direction="asc"===this.direction?"desc":"asc":this.direction=s,s="asc"==this.direction?1:-1,n.$table.trigger("tablesort:start",[n]),n.log("Sorting by "+this.index+" "+this.direction),n.$table.css("display"),setTimeout(function(){n.$sortCells.removeClass(n.settings.asc+" "+n.settings.desc);for(var r=0,c=h.length;c>r;r++)d.push({index:r,cell:a[r],row:l[r],value:h[r]});d.sort(function(t,e){return t.value>e.value?1*s:t.value2e3?200:10))},log:function(e){(t.tablesort.DEBUG||this.settings.debug)&&console&&console.log&&console.log("[tablesort] "+e)},destroy:function(){return this.$sortCells.unbind("click.tablesort"),this.$table.data("tablesort",null),null}},t.tablesort.DEBUG=!1,t.tablesort.defaults={debug:t.tablesort.DEBUG,asc:"sorted ascending",desc:"sorted descending"},t.fn.tablesort=function(e){var s,i;return this.each(function(){s=t(this),i=s.data("tablesort"),i&&i.destroy(),s.data("tablesort",new t.tablesort(s,e))})}}(window.Zepto||window.jQuery); \ No newline at end of file diff --git a/puppetboard/static/js/tables.js b/puppetboard/static/js/tables.js new file mode 100644 index 0000000..25c4434 --- /dev/null +++ b/puppetboard/static/js/tables.js @@ -0,0 +1,35 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var $; + + $ = jQuery; + + $(function() {}); + + if ($('th.default-sort').data()) { + $('table.sortable').tablesort().data('tablesort').sort($("th.default-sort"), "desc"); + } + + $('thead th.date').data('sortBy', function(th, td, tablesort) { + return moment.utc(td.text()).unix(); + }); + + $('input.filter-table').parent('div').removeClass('hide'); + + $("input.filter-table").on("keyup", function(e) { + var ev, rex; + rex = new RegExp($(this).val(), "i"); + $(".searchable tr").hide(); + $(".searchable tr").filter(function() { + return rex.test($(this).text()); + }).show(); + if (e.keyCode === 27) { + $(e.currentTarget).val(""); + ev = $.Event("keyup"); + ev.keyCode = 13; + $(e.currentTarget).trigger(ev); + return e.currentTarget.blur(); + } + }); + +}).call(this); diff --git a/puppetboard/templates/_macros.html b/puppetboard/templates/_macros.html index 3817470..2ebb484 100644 --- a/puppetboard/templates/_macros.html +++ b/puppetboard/templates/_macros.html @@ -46,39 +46,6 @@ {%- endmacro %} -{% macro facts_graph(facts, autofocus=False, condensed=False, show_node=False, margin_top=20, margin_bottom=20) -%} - - -
- -{%- endmacro %} - {% macro status_counts(caller, status, node_name, events, current_env, unreported_time=False, report_hash=False) -%} {{ status|upper }} {% if status == 'unreported' %} diff --git a/puppetboard/templates/fact.html b/puppetboard/templates/fact.html index dbef184..e9a4b83 100644 --- a/puppetboard/templates/fact.html +++ b/puppetboard/templates/fact.html @@ -1,10 +1,46 @@ {% extends 'layout.html' %} {% import '_macros.html' as macros %} -{% block content %} -

{{name}}{% if value %}/{{value}}{% endif %} ({{facts|length}})

+ {% if render_graph %} -{{macros.facts_graph(facts, autofocus=True, show_node=True, margin_bottom=10)}} + +{% block javascript %} +var chart = null; +var data = [ +{% for fact in facts|groupby('value') %} + { + label: '{{ fact.grouper.replace("\n", " ") }}', + value: {{ fact.list|length }} + }, +{% endfor %} + { + value: 0, +} +] +var fact_values = data.map(function(item) { return [item.label, item.value]; }).filter(function(item){return item[0];}).sort(function(a,b){return b[1] - a[1];}); +var realdata = fact_values.slice(0, 15); +var otherdata = fact_values.slice(15); +if (otherdata.length > 0) { + realdata.push(["other", otherdata.reduce(function(a,b){return a + b[1];},0)]); +} +{% endblock javascript %} + +{% block onload_script %} + $('table').tablesort(); + chart = c3.generate({ + bindto: '#factChart', + data: { + columns: realdata, + type : 'donut', + } +}); +{% endblock onload_script %} {% endif %} + +{% block content %} +
+

{{name}}{% if value %}/{{value}}{% endif %} ({{facts|length}})

+ + {% if value %} {{macros.facts_table(facts, current_env=current_env, autofocus=True, show_node=True, show_value=False, margin_bottom=10)}} {% else %} diff --git a/puppetboard/templates/index.html b/puppetboard/templates/index.html index d77195a..20e028e 100644 --- a/puppetboard/templates/index.html +++ b/puppetboard/templates/index.html @@ -12,6 +12,7 @@ {% endblock script %} {% endif %} {% endblock head %} + {% block content %} {% if config.REFRESH_RATE > 0 %} diff --git a/puppetboard/templates/layout.html b/puppetboard/templates/layout.html index ab9f649..7bd1a3c 100644 --- a/puppetboard/templates/layout.html +++ b/puppetboard/templates/layout.html @@ -41,14 +41,20 @@ + + + + {% block script %} {% endblock script %} - {% block script %} {% endblock script %} {% block head %} {% endblock head %} From e28eb5027d3e72b9f5eb80fc1768c930156613e8 Mon Sep 17 00:00:00 2001 From: Mike Terzo Date: Tue, 31 Jan 2017 03:00:01 -0500 Subject: [PATCH 3/9] Adding configuration option to specify the bar chart --- README.rst | 4 ++++ puppetboard/default_settings.py | 1 + puppetboard/docker_settings.py | 2 ++ puppetboard/templates/fact.html | 2 +- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 4137c42..f936eb1 100644 --- a/README.rst +++ b/README.rst @@ -219,6 +219,9 @@ Other settings that might be interesting in no particular order: * ``ENABLE_QUERY``: Defaults to ``True`` causing a Query tab to show up in the web interface allowing users to write and execute arbitrary queries against a set of endpoints in PuppetDB. Change this to ``False`` to disable this. +* ``GRAPH_TYPE```: Specify the type of graph to display. Default is + pie, other good option is donut. Other choices can be found here: + `_C3JS_documentation` * ``GRAPH_FACTS``: A list of fact names to tell PuppetBoard to generate a pie-chart on the fact page. With some fact values being unique per node, like ipaddress, uuid, and serial number, as well as structured facts it was @@ -241,6 +244,7 @@ Other settings that might be interesting in no particular order: .. _pypuppetdb documentation: http://pypuppetdb.readthedocs.org/en/v0.1.0/quickstart.html#ssl .. _Flask documentation: http://flask.pocoo.org/docs/0.10/quickstart/#sessions +.. _C3JS_documentation: http://c3js.org/examples.html#chart Puppet Enterprise ----------------- diff --git a/puppetboard/default_settings.py b/puppetboard/default_settings.py index 9019488..717925b 100644 --- a/puppetboard/default_settings.py +++ b/puppetboard/default_settings.py @@ -21,6 +21,7 @@ TABLE_COUNT_SELECTOR = [10, 20, 50, 100, 500] OFFLINE_MODE = False ENABLE_CATALOG = False OVERVIEW_FILTER = None +GRAPH_TYPE = 'pie' GRAPH_FACTS = ['architecture', 'clientversion', 'domain', diff --git a/puppetboard/docker_settings.py b/puppetboard/docker_settings.py index fa0055c..e32ac2a 100644 --- a/puppetboard/docker_settings.py +++ b/puppetboard/docker_settings.py @@ -47,6 +47,8 @@ GRAPH_FACTS = [x.strip() for x in os.getenv('GRAPH_FACTS', GRAPH_FACTS_DEFAULT).split(',')] +GRAPH_TYPE = os.getenv('GRAPH_TYPE', 'pie') + # Tuples are hard to express as an environment variable, so here # the tupple can be listed as a list of items # export INVENTORY_FACTS="Hostname, fqdn, IP Address, ipaddress,.. etc" diff --git a/puppetboard/templates/fact.html b/puppetboard/templates/fact.html index e9a4b83..2e3380f 100644 --- a/puppetboard/templates/fact.html +++ b/puppetboard/templates/fact.html @@ -30,7 +30,7 @@ if (otherdata.length > 0) { bindto: '#factChart', data: { columns: realdata, - type : 'donut', + type : '{{config.GRAPH_TYPE|default('pie')}}', } }); {% endblock onload_script %} From b82a305952f5885a44c6ae7741808095e3f7a630 Mon Sep 17 00:00:00 2001 From: Mike Terzo Date: Tue, 31 Jan 2017 03:50:11 -0500 Subject: [PATCH 4/9] When searching metrics, the search button doesn't disappear. --- puppetboard/templates/metrics.html | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/puppetboard/templates/metrics.html b/puppetboard/templates/metrics.html index e3d4245..eb0440e 100644 --- a/puppetboard/templates/metrics.html +++ b/puppetboard/templates/metrics.html @@ -2,13 +2,18 @@ {% block content %}

Metrics

- +
-
    + + + Metric + + {% for metric in metrics %} -
  • - {{metric}} -
  • + + + {% endfor %} - + +
    {{metric}}
    {% endblock content %} From 347749c0e183905b17f361c5d14801781e8bcb49 Mon Sep 17 00:00:00 2001 From: redref Date: Tue, 31 Jan 2017 16:18:11 +0100 Subject: [PATCH 5/9] Footer - grid padding in the same unit as text --- puppetboard/static/css/puppetboard.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/puppetboard/static/css/puppetboard.css b/puppetboard/static/css/puppetboard.css index 4f7f478..19506f5 100644 --- a/puppetboard/static/css/puppetboard.css +++ b/puppetboard/static/css/puppetboard.css @@ -14,7 +14,7 @@ h1.ui.header.no-margin-bottom { } .ui.grid.padding-bottom { - padding-bottom: 40px !important; + padding-bottom: 4em !important; } .status { From 17f902c18fc9a5d1ba86784d7dafce72dff55a33 Mon Sep 17 00:00:00 2001 From: redref Date: Tue, 31 Jan 2017 16:19:30 +0100 Subject: [PATCH 6/9] Fix filter-list behavior with a class flag --- puppetboard/static/coffeescript/lists.coffee | 4 +- puppetboard/static/js/lists.js | 6 +-- puppetboard/templates/facts.html | 44 ++++++++++---------- puppetboard/templates/metrics.html | 19 ++++----- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/puppetboard/static/coffeescript/lists.coffee b/puppetboard/static/coffeescript/lists.coffee index 86e89ec..adf347b 100644 --- a/puppetboard/static/coffeescript/lists.coffee +++ b/puppetboard/static/coffeescript/lists.coffee @@ -1,11 +1,9 @@ $ = jQuery -$ -> -$('input.filter-list').parent('div').removeClass('hide') $("input.filter-list").on "keyup", (e) -> rex = new RegExp($(this).val(), "i") $(".searchable li").hide() - $(".searchable li").parent().parent().hide() + $(".searchable li").parent().parent('.list_hide_segment').hide() $(".searchable li").filter( -> rex.test $(this).text() ).show() diff --git a/puppetboard/static/js/lists.js b/puppetboard/static/js/lists.js index afaee34..206ed5d 100644 --- a/puppetboard/static/js/lists.js +++ b/puppetboard/static/js/lists.js @@ -4,15 +4,11 @@ $ = jQuery; - $(function() {}); - - $('input.filter-list').parent('div').removeClass('hide'); - $("input.filter-list").on("keyup", function(e) { var ev, rex; rex = new RegExp($(this).val(), "i"); $(".searchable li").hide(); - $(".searchable li").parent().parent().hide(); + $(".searchable li").parent().parent('.list_hide_segment').hide(); $(".searchable li").filter(function() { return rex.test($(this).text()); }).show(); diff --git a/puppetboard/templates/facts.html b/puppetboard/templates/facts.html index 345b293..ce3fe77 100644 --- a/puppetboard/templates/facts.html +++ b/puppetboard/templates/facts.html @@ -1,29 +1,29 @@ {% extends 'layout.html' %} {% block content %} -
    +
    -
    - {%- set facts_count = 0 -%} - {%- set break = facts_len//4 + 1 -%} - {%- for key,facts_list in facts_dict %} -
    - {{key}} -
      - {%- for fact in facts_list %} -
    • {{fact}}
    • - {%- endfor %} -
    -
    - {%- set facts_count = facts_count + facts_list|length -%} - {%- if facts_count >= break -%} -
    -
    - {%- set break = facts_len//4 + 1 + break -%} - {%- endif -%} - {%- set facts_count = facts_count + 5 -%} - {% endfor %} -
    +
    + {%- set facts_count = 0 -%} + {%- set break = facts_len//4 + 1 -%} + {%- for key,facts_list in facts_dict %} +
    + {{key}} +
      + {%- for fact in facts_list %} +
    • {{fact}}
    • + {%- endfor %} +
    +
    + {%- set facts_count = facts_count + facts_list|length -%} + {%- if facts_count >= break -%} +
    +
    + {%- set break = facts_len//4 + 1 + break -%} + {%- endif -%} + {%- set facts_count = facts_count + 5 -%} + {% endfor %} +
    {% endblock content %} diff --git a/puppetboard/templates/metrics.html b/puppetboard/templates/metrics.html index eb0440e..844ad41 100644 --- a/puppetboard/templates/metrics.html +++ b/puppetboard/templates/metrics.html @@ -1,19 +1,14 @@ {% extends 'layout.html' %} {% block content %}

    Metrics

    -
    - +
    +
    - - - Metric - - +
      {% for metric in metrics %} -
    - - +
  • + {{metric}} +
  • {% endfor %} - -
    {{metric}}
    +
{% endblock content %} From 851797e4c647bb5c427715774b20a936c2ccab55 Mon Sep 17 00:00:00 2001 From: redref Date: Tue, 31 Jan 2017 17:11:41 +0100 Subject: [PATCH 7/9] filter-list handling reload --- puppetboard/static/coffeescript/lists.coffee | 17 +++++++++---- puppetboard/static/js/lists.js | 25 ++++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/puppetboard/static/coffeescript/lists.coffee b/puppetboard/static/coffeescript/lists.coffee index adf347b..5a4968e 100644 --- a/puppetboard/static/coffeescript/lists.coffee +++ b/puppetboard/static/coffeescript/lists.coffee @@ -1,7 +1,6 @@ $ = jQuery -$("input.filter-list").on "keyup", (e) -> - rex = new RegExp($(this).val(), "i") - +filter_list = (val) -> + rex = new RegExp(val, "i") $(".searchable li").hide() $(".searchable li").parent().parent('.list_hide_segment').hide() $(".searchable li").filter( -> @@ -10,10 +9,20 @@ $("input.filter-list").on "keyup", (e) -> $(".searchable li").filter( -> rex.test $(this).text() ).parent().parent().show() - +$("input.filter-list").on "keyup", (e) -> + # If key is escape, reset value if e.keyCode is 27 $(e.currentTarget).val "" ev = $.Event("keyup") ev.keyCode = 13 $(e.currentTarget).trigger(ev) e.currentTarget.blur() + else + filter_list($(this).val()) +$("input.filter-list").ready -> + elem = $("input.filter-list") + elem.focus() + val = elem.val() + filter_list(val) + # Force cursor at the end + elem.val('').val(val) diff --git a/puppetboard/static/js/lists.js b/puppetboard/static/js/lists.js index 206ed5d..9f8d455 100644 --- a/puppetboard/static/js/lists.js +++ b/puppetboard/static/js/lists.js @@ -1,27 +1,42 @@ // Generated by CoffeeScript 1.9.3 (function() { - var $; + var $, filter_list; $ = jQuery; - $("input.filter-list").on("keyup", function(e) { - var ev, rex; - rex = new RegExp($(this).val(), "i"); + filter_list = function(val) { + var rex; + rex = new RegExp(val, "i"); $(".searchable li").hide(); $(".searchable li").parent().parent('.list_hide_segment').hide(); $(".searchable li").filter(function() { return rex.test($(this).text()); }).show(); - $(".searchable li").filter(function() { + return $(".searchable li").filter(function() { return rex.test($(this).text()); }).parent().parent().show(); + }; + + $("input.filter-list").on("keyup", function(e) { + var ev; if (e.keyCode === 27) { $(e.currentTarget).val(""); ev = $.Event("keyup"); ev.keyCode = 13; $(e.currentTarget).trigger(ev); return e.currentTarget.blur(); + } else { + return filter_list($(this).val()); } }); + $("input.filter-list").ready(function() { + var elem, val; + elem = $("input.filter-list"); + elem.focus(); + val = elem.val(); + filter_list(val); + return elem.val('').val(val); + }); + }).call(this); From f6e04ca67f85c250953031bf99550f841f48471c Mon Sep 17 00:00:00 2001 From: redref Date: Mon, 30 Jan 2017 16:20:31 +0100 Subject: [PATCH 8/9] Remove non-needed columns option --- puppetboard/templates/_macros.html | 2 +- puppetboard/templates/node.html | 2 +- puppetboard/templates/reports.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/puppetboard/templates/_macros.html b/puppetboard/templates/_macros.html index 2ebb484..fe28cc5 100644 --- a/puppetboard/templates/_macros.html +++ b/puppetboard/templates/_macros.html @@ -57,7 +57,7 @@ {% endif %} {%- endmacro %} -{% macro datatable_init(table_html_id, ajax_url, default_length, length_selector, extra_options=None, columns) -%} +{% macro datatable_init(table_html_id, ajax_url, default_length, length_selector, extra_options=None) -%} // Init datatable $.fn.dataTable.ext.errMode = 'throw'; var table = $('#{{ table_html_id }}').DataTable({ diff --git a/puppetboard/templates/node.html b/puppetboard/templates/node.html index 9b7964d..507e877 100644 --- a/puppetboard/templates/node.html +++ b/puppetboard/templates/node.html @@ -17,7 +17,7 @@ 'pagingType': 'simple', "bFilter": false, {% endmacro %} -{{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, columns=columns, extra_options=extra_options) }} +{{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options) }} {% endblock onload_script %} {% block content %} diff --git a/puppetboard/templates/reports.html b/puppetboard/templates/reports.html index 1d16d03..d8fe86a 100644 --- a/puppetboard/templates/reports.html +++ b/puppetboard/templates/reports.html @@ -33,7 +33,7 @@ // No initial loading "deferLoading": true, {% endmacro %} - {{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node_name), default_length=config.NORMAL_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options, columns=columns) }} + {{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node_name), default_length=config.NORMAL_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options) }} // Event listener for status filters function status_filter_change(){ From 1432cfeac24d23b2e7b4c9529216fd13f3d6999d Mon Sep 17 00:00:00 2001 From: redref Date: Tue, 31 Jan 2017 19:14:20 +0100 Subject: [PATCH 9/9] Fix tablesort when no pie - +indent --- puppetboard/templates/fact.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/puppetboard/templates/fact.html b/puppetboard/templates/fact.html index 2e3380f..ffaa5ce 100644 --- a/puppetboard/templates/fact.html +++ b/puppetboard/templates/fact.html @@ -1,9 +1,8 @@ {% extends 'layout.html' %} {% import '_macros.html' as macros %} -{% if render_graph %} - {% block javascript %} +{% if render_graph %} var chart = null; var data = [ {% for fact in facts|groupby('value') %} @@ -22,19 +21,21 @@ var otherdata = fact_values.slice(15); if (otherdata.length > 0) { realdata.push(["other", otherdata.reduce(function(a,b){return a + b[1];},0)]); } +{% endif %} {% endblock javascript %} {% block onload_script %} - $('table').tablesort(); - chart = c3.generate({ + $('table').tablesort(); + {% if render_graph %} + chart = c3.generate({ bindto: '#factChart', data: { columns: realdata, type : '{{config.GRAPH_TYPE|default('pie')}}', } -}); + }); + {% endif %} {% endblock onload_script %} -{% endif %} {% block content %}