diff options
| author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-05-14 16:12:21 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-06-17 13:21:28 +0200 | 
| commit | 0122c68228b0cf3f1ec152481bcb7c22248248d3 (patch) | |
| tree | 634b407ea8c7b7b778c485744fcea9ac493f5541 | |
| parent | 014eddee87b0e6e871cf4a201884cf60a41cc63e (diff) | |
| download | Ishtar-0122c68228b0cf3f1ec152481bcb7c22248248d3.tar.bz2 Ishtar-0122c68228b0cf3f1ec152481bcb7c22248248d3.zip | |
Statistics - JS and templates to manage graphs and tables
| -rw-r--r-- | archaeological_operations/models.py | 6 | ||||
| -rw-r--r-- | ishtar_common/models.py | 9 | ||||
| -rw-r--r-- | ishtar_common/static/js/ishtar-map.js | 35 | ||||
| -rw-r--r-- | ishtar_common/static/js/ishtar.js | 279 | ||||
| -rw-r--r-- | ishtar_common/templates/base.html | 14 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/DataTables-tabs.html | 14 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/DataTables.html | 64 | ||||
| -rw-r--r-- | ishtar_common/views_item.py | 31 | ||||
| -rw-r--r-- | version.py | 4 | 
9 files changed, 387 insertions, 69 deletions
| diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 4f180c3d5..d18b76f80 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -17,6 +17,7 @@  # See the file COPYING for details. +from collections import OrderedDict  import datetime  from itertools import groupby @@ -530,6 +531,11 @@ class Operation(ClosedItem, DocumentItem, BaseHistorizedItem, QRCodeItem,      # statistics      STATISTIC_MODALITIES = ["year", "operation_type__label",                              "towns__cached_label"] +    STATISTIC_MODALITIES_OPTIONS = OrderedDict([ +        ('year', _("Year")), +        ("operation_type__label",  _("Operation type")), +        ("towns__cached_label",  _("Towns")), +    ])      # search parameters      BOOL_FIELDS = ['end_date__isnull', 'virtual_operation', diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 7aa8706b3..8e5983a45 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1931,10 +1931,13 @@ class TemplateItem:  class StatisticItem: -    STATISTIC_MODALITIES = []  # example: "operation type", "material type" +    STATISTIC_MODALITIES = []  # example: "year", "operation_type__label" +    STATISTIC_MODALITIES_OPTIONS = OrderedDict()  # example: +    # OrderedDict([('year', _("Year")), +    #              ("operation_type__label",  _("Operation type"))])      STATISTIC_SUM_VARIABLE = OrderedDict( -        (("pk", _("number")),) -    )  # example: "price", "volume" +        (("pk", _("Number")),) +    )  # example: "Price", "Volume"  class BaseHistorizedItem(StatisticItem, TemplateItem, FullSearch, Imported, diff --git a/ishtar_common/static/js/ishtar-map.js b/ishtar_common/static/js/ishtar-map.js index 1b0d4384b..a93813e61 100644 --- a/ishtar_common/static/js/ishtar-map.js +++ b/ishtar_common/static/js/ishtar-map.js @@ -27,6 +27,41 @@ var geolocation = {};  var geoloc_feature = {};  var geoloc_activated = {}; +var fetching_msg = "Fetching data..."; + +var _map_submit_search = function(query_vars, name, source){ +    var modal_base_text = $('.modal-progress .modal-header').html(); +    $('.modal-progress .modal-header').html(fetching_msg); +    $('.modal-progress').modal('show'); +    var data = search_get_query_data(query_vars, name); +    var nb_select = jQuery("#id_" + name + "-length_map").val(); +    if (!nb_select) nb_select = 10; + +    var url = source + "json-map?length=" + nb_select + "&submited=1&" + data; +    var use_map_limit = false; +    if(data.indexOf("no_limit=true") == -1){ +        url += "&limit=" + current_map_limit; +        use_map_limit = true; +    } +    $.getJSON(url, function(data) { +        var timestamp = Math.floor(Date.now() / 1000); +        var map_id = "map-" + timestamp; +        $('.modal-progress .modal-header').html("{% trans 'Render map...' %}"); + +        var html = render_map(map_id, use_map_limit); +        $("#tab-content-map-" + name).html(html); +        $("#id_" + name + "-length_map").change(map_submit_search); +        if ($('.modal-progress').length > 0){ +            $('.modal-progress').modal('hide'); +            $('.modal-progress .modal-header').html(modal_base_text); +        } +        register_map(map_id, data); +    }); + +    return false; + +}; +  var geoloc_activated_message = function(map_id){      setTimeout(function(){ diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 2527c1bd7..54823968c 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -1095,6 +1095,33 @@ var get_hover_div = function(table_cols, data){      return hover;  }; +var _gallery_submit_search = function(image_page, query_vars, name, source){ +    if (image_page) { +        current_image_page = image_page; +    } else { +        current_image_page = 1; +    } +    $('.modal-progress').modal('show'); +    var data = search_get_query_data(query_vars, name); +    var nb_select = jQuery("#id_" + name + "-length_image").val(); +    if (!nb_select) nb_select = 10; + +    var url = source + "json-image?length=" + nb_select + "&submited=1&" + data; +    $.getJSON(url, function(data) { +        var timestamp = Math.floor(Date.now() / 1000); +        var gallery_id = "gallery-" + timestamp; +        $("#tab-content-gallery-" + name).html( +            render_gallery(data, name, nb_select, gallery_id)); +        $("#id_" + name + "-length_image").change(gallery_submit_search); +        register_image_gallery(gallery_id); +        $('.card[data-toggle="tooltip"]').tooltip(); +        if ($('.modal-progress').length > 0){ +            $('.modal-progress').modal('hide'); +        } +    }); +    return false; +} +  var render_gallery = function(data_table, table_name, nb_select, gallery_id){      var html = '<div class="ishtar-gallery-wrapper container-fluid">';      html += render_paginate_select(table_name, 'image', nb_select); @@ -1343,6 +1370,7 @@ var register_map = function(map_id, points){  var main_submit_search = function(){      if (current_tab == "table") datatable_submit_search();      if (current_tab == "gallery") gallery_submit_search(); +    if (current_tab == "stats") stats_submit_search();      if (current_tab == "map") map_submit_search();  }; @@ -1376,3 +1404,254 @@ var search_get_query_data = function(query_vars, table_name){      }      return data;  }; + +var registered_stats = false; + +var register_stats = function(query_vars, name, source){ +    if (registered_stats) return; +    registered_stats = true; +    $("#stats-form-" + name + " select").on('change', function() { +            _stats_submit_search(query_vars, name, source); +        } +    ); +    $('#chart-img-display-' + name).click(function(){ +        $('#chart-img-' + name).hide(); +        $('#img-' + name).html( +        $('<img/>').attr( +                'src', $('#chart-' + name).jqplotToImageStr({}) +        ) +        ); +        $('#chart-img-' + name).show('slow'); +    }); +}; + +var _stats_submit_search = function(query_vars, name, source){ +    $('.modal-progress').modal('show'); + +    var data = search_get_query_data(query_vars, name); +    register_stats(query_vars, name, source); + +    var url = source + "json-stats?submited=1&" + data; +    var modality_1 = $("#stats_modality_1-" + name).val(); +    if (modality_1) url += '&stats_modality_1=' + modality_1; +    var modality_2 = $("#stats_modality_2-" + name).val(); +    if (modality_2) url += '&stats_modality_2=' + modality_2; +    $.getJSON(url, function(data) { +        var timestamp = Math.floor(Date.now() / 1000); +        var stats_id = "stats-" + timestamp; +        $("#tab-content-stats-" + name).html( +            render_stats(data, name)); +        if ($('.modal-progress').length > 0){ +            $('.modal-progress').modal('hide'); +        } +    }); +    return false; +} + +var stats_showmarker = false; +var stats_incompatible_modality = "This graph type accept only one modality."; +var stats_current_graph; + +var _render_stats_table = function(stats_values, name){ +    var modality_1 = $("#stats_modality_1-" + name).val(); +    var modality_2 = $("#stats_modality_2-" + name).val(); +    var rows = new Array(); + +    var current_row = new Array(); +    var html = ""; +    html += "<table class='table w-75 mt-4 pt-4 mx-auto'><thead>"; +    html += "<tr><th>"; +    var modality_1_lbl = $('#stats_modality_1-' + name + ' option:selected').text(); +    current_row.push(modality_1_lbl); +    html += modality_1_lbl; +    if (modality_2 && modality_2 != modality_1){ +        html += "</th><th>"; +        var modality_2_lbl = $('#stats_modality_2-' + name + ' option:selected').text(); +        html += modality_2_lbl; +        current_row.push(modality_2_lbl); +    } +    html += "</th><th>"; +    var sum_lbl = $('#stats_sum-' + name + ' option:selected').text(); +    html += sum_lbl; +    current_row.push(sum_lbl); +    html += "</th></tr></thead><tbody>"; +    rows.push(current_row); + +    if (modality_2 && modality_2 != modality_1){ +        for (idx in stats_values){ +            var start_row = ""; +            row_content = ""; +            for (inner_idx in stats_values[idx][1]){ +                current_row = new Array(); +                var colspan = parseInt(inner_idx) + 1; +                start_row = "<tr><td rowspan='" + colspan + "'>" + stats_values[idx][0] + "</td>"; +                current_row.push(stats_values[idx][0]); +                if (inner_idx > 0) row_content += "<tr>"; +                row_content += "<td>" + stats_values[idx][1][inner_idx][0] + "</td>"; +                current_row.push(stats_values[idx][1][inner_idx][0]); +                row_content += "<td>" + stats_values[idx][1][inner_idx][1] + "</td></tr>"; +                current_row.push(stats_values[idx][1][inner_idx][1]); +                rows.push(current_row); +            } +            html += start_row + row_content; +        } +    } else { +        for (idx in stats_values){ +            current_row = new Array(); +            html += "<tr><td>" + stats_values[idx][0] + "</td>"; +            current_row.push(stats_values[idx][0]); +            html += "<td>" + stats_values[idx][1] + "</td></tr>"; +            current_row.push(stats_values[idx][1]); +            rows.push(current_row); +        } +    } + +    html += "</tbody></table>"; +    $("#charts-" + name).hide(); +    $("#stats-table-content-" + name).html(html); +    $("#stats-table-" + name).show(); + +    var csv_content = "data:text/csv;charset=utf-8," + rows.map(e => e.join(",")).join("\n"); +    var encoded_uri = encodeURI(csv_content); +    $("#stats-table-csv-" + name).attr("href", encoded_uri); +    $("#stats-table-csv-" + name).attr("download", "ishtar-stats.csv"); +}; + +var render_stats = function(stats_values, name){ +    var stats_type = $("#stats_renderer-" + name).val(); + +    if (!stats_values || !stats_values['data']) return; +    stats_values = stats_values['data']; + +    if (stats_current_graph){ +        stats_current_graph.destroy(); +    } +    if (stats_type == "table"){ +        return _render_stats_table(stats_values, name); +    } + +    $("#stats-table-" + name).hide(); +    $("#charts-" + name).show(); +    var modality_1 = $("#stats_modality_1-" + name).val(); +    var modality_2 = $("#stats_modality_2-" + name).val(); +     +    stats_xaxis = { +        label: $('#stats_modality_1-' + name + ' option:selected').text() +    }; +     +    var stats_help = $("#stats-zoom-help-" + name); + +    if (stats_type == "pie"){ +        stats_help.hide(); +        if (modality_2){ +            display_info(stats_incompatible_modality); +            return; +        } +    } else { +        stats_help.show(); +        var stats_xaxis_tickoptions; +        if (modality_1 == "year"){ +            stats_xaxis_tickoptions = {formatString: "%d"}; +        } else { +            stats_xaxis_tickoptions = {angle:-25}; +        } +        stats_xaxis["tickOptions"] = stats_xaxis_tickoptions +    } +     +    var stats_showmarker = false; +    if (stats_values.length < 25){ +        stats_showmarker = true; +    } +    var jqvalues = new Array(); +    var ticks = new Array(); +    var series = new Array(); +    var series_conf = new Array(); +    if (modality_2 && modality_2 != modality_1){ +        for (idx in stats_values){ +            ticks.push(stats_values[idx][0]); +            var serie_values = stats_values[idx][1]; +            var current_serie_values = new Array(); +            for (inner_idx in serie_values){ +                var serie_value = serie_values[inner_idx][0]; +                if (series.indexOf(serie_value) == -1){ +                    series.push(serie_value); +                    var fill_values = new Array(); +                    if (idx > 0){ // put 0 for previous items +                        for (var fill_idx = 0 ; fill_idx < idx ; fill_idx++ ){ +                            fill_values.push(0); +                        } +                    } +                    jqvalues.push(fill_values); +                } +                current_serie_values.push(serie_value); +                var current_value = serie_values[inner_idx][1]; +                jqvalues[series.indexOf(serie_value)].push(current_value); +            } +            // put 0 for missing series for this item +            for (idx_serie in series){ +                if (current_serie_values.indexOf(series[idx_serie]) == -1){ +                    jqvalues[series.indexOf(series[idx_serie])].push(0); +                } +            } +        } +        stats_xaxis['ticks'] = ticks; +    } else { +        jqvalues = [stats_values]; +        series.push("Total"); +    } +    if (stats_type != "pie"){ +        stats_xaxis['renderer'] = $.jqplot.CategoryAxisRenderer; +        stats_xaxis['labelRenderer'] = $.jqplot.CanvasAxisLabelRenderer; +        stats_xaxis['tickRenderer'] = $.jqplot.CanvasAxisTickRenderer; +    } + +    var stats_renderer; +    if (stats_type == "bar"){ +        stats_renderer = $.jqplot.BarRenderer; +    } else if (stats_type == "pie"){ +        stats_renderer = $.jqplot.PieRenderer; +    } +    for (idx in series){ +        var serie_conf = { +            label: series[idx], +            showmarker: stats_showmarker +        }; +        if (stats_renderer){ +            serie_conf["renderer"] = stats_renderer; +        } +        serie_conf["rendererOptions"] = { +            padding: 8, showDataLabels: true, +            dataLabels: 'value', +            fill: false, sliceMargin: 4 +        }; +        series_conf.push(serie_conf); +    } +     +    var stats_options = { +            axes: { +                xaxis: stats_xaxis, +                yaxis: { +                    label: $('#stats_sum-' + name + ' option:selected').text(), +                    min: 0 +                } +            }, +            highlighter: { +                show: true, +                tooltipAxes: 'y', +                sizeAdjust: 7.5 +            }, +            series: series_conf, +            legend: { show:true, location: 'e', placement: 'outside' } +    }; +    if (stats_type != "pie"){ +        stats_options["cursor"] = { +                show: true, +                zoom: true, +                showTooltip: false +        } +    } + +    stats_current_graph = $.jqplot('chart-' + name, +        jqvalues, stats_options +    ); +}; diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 8d569711e..f88f1eba6 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -32,6 +32,17 @@      <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/ishtar.js?ver={{VERSION}}"></script>      <script language="javascript" type="text/javascript"              src="{{STATIC_URL}}datatables/i18n/{{LANGUAGE_CODE}}.js?ver={{VERSION}}"></script> +    <!-- jqplot --> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/jquery.jqplot.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasTextRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.highlighter.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.barRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.pieRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.dateAxisRenderer.min.js?ver={{VERSION}}"></script> +    <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.cursor.min.js?ver={{VERSION}}"></script>      {{EXTRA_JS|safe}}      <script type='text/javascript'>      var static_path = "{{STATIC_URL}}"; @@ -54,6 +65,8 @@      var select_only_one_msg = "{% trans "Select only one item." %}";      var YES = "{% trans 'yes' %}";      var NO = "{% trans 'no' %}"; +    var fetching_msg = "{% trans 'Fetching data...' %}"; +    var stats_incompatible_modality = "{% trans 'This graph type accept only one modality.' %}";      var show_msg = "{% trans "Show" %}";      var entries_msg = "{% trans "entries" %}";      var info_show_msg = "{% trans "Showing" %}"; @@ -85,6 +98,7 @@      <link rel="stylesheet" href="{{STATIC_URL}}datatables/dataTables.bootstrap4.min.css?ver={{VERSION}}">      <link type="text/css" rel="stylesheet" href="{{STATIC_URL}}lightgallery/css/lightgallery.css?ver={{VERSION}}">      <link rel="stylesheet" href="{{STATIC_URL}}ol/ol.css?ver={{VERSION}}"> +    <link rel="stylesheet" href="{{STATIC_URL}}js/jqplot/jquery.jqplot.min.css?ver={{VERSION}}" />      <link rel="stylesheet" href="{{STATIC_URL}}media/styles.css?ver={{VERSION}}">      {% for url_css in JQGRID_CSS %}<link rel="stylesheet" href="{{url_css}}?ver={{VERSION}}">{% endfor %}      {{EXTRA_CSS|safe}} diff --git a/ishtar_common/templates/blocks/DataTables-tabs.html b/ishtar_common/templates/blocks/DataTables-tabs.html index 73653061d..a2f354240 100644 --- a/ishtar_common/templates/blocks/DataTables-tabs.html +++ b/ishtar_common/templates/blocks/DataTables-tabs.html @@ -22,6 +22,14 @@            {% trans "Map" %}        </a>    </li>{% endif %} +  {% if current_model.STATISTIC_MODALITIES %} +  <li class="nav-item"> +    <a class="nav-link" id="tab-stats-{{name}}" data-toggle="tab" +       href="#tab-content-stats-{{name}}" role="tab" +       aria-controls="tab-content-stats-{{name}}" aria-selected="true"> +        {% trans "Statistics" %} +    </a> +  </li>{% endif %}  </ul>  <div class="tab-content"> @@ -38,4 +46,10 @@         id="tab-content-map-{{name}}" role="tabpanel"         aria-labelledby="tab-map-{{name}}">    </div>{% endif %} +  {% if current_model.STATISTIC_MODALITIES %} +  <div class="tab-pane" +       id="tab-content-stats-{{name}}" role="tabpanel" +       aria-labelledby="tab-stats-{{name}}"> +       {% include "blocks/DataTables-stats.html" %} +  </div>{% endif %}  </div> diff --git a/ishtar_common/templates/blocks/DataTables.html b/ishtar_common/templates/blocks/DataTables.html index a20a151a9..01aa7519d 100644 --- a/ishtar_common/templates/blocks/DataTables.html +++ b/ishtar_common/templates/blocks/DataTables.html @@ -67,6 +67,12 @@ $("#tab-map-{{name}}").click(function(){      map_submit_search();  });  {% endif %} +{% if current_model.STATISTIC_MODALITIES %} +$("#tab-stats-{{name}}").click(function(){ +    current_tab = "stats"; +    stats_submit_search(); +}); +{% endif %}  var query_vars = new Array({{col_idx|safe}}); @@ -74,65 +80,17 @@ var selItems_{{sname}} = new Array();  {% if gallery %}  gallery_submit_search = function(image_page){ -    if (image_page) { -        current_image_page = image_page; -    } else { -        current_image_page = 1; -    } -    $('.modal-progress').modal('show'); -    var data = search_get_query_data(query_vars, "{{name}}"); -    var nb_select = jQuery("#id_{{name}}-length_image").val(); -    if (!nb_select) nb_select = 10; - -    var url = "{{source}}json-image?length=" + nb_select + "&submited=1&" + data; -    $.getJSON(url, function(data) { -        var timestamp = Math.floor(Date.now() / 1000); -        var gallery_id = "gallery-" + timestamp; -        $("#tab-content-gallery-{{name}}").html( -            render_gallery(data, "{{name}}", nb_select, gallery_id)); -        $("#id_{{name}}-length_image").change(gallery_submit_search); -        register_image_gallery(gallery_id); -        $('.card[data-toggle="tooltip"]').tooltip(); -        if ($('.modal-progress').length > 0){ -            $('.modal-progress').modal('hide'); -        } -    }); -    return false; +    return _gallery_submit_search(image_page, query_vars, "{{name}}", "{{source}}");  };  {% endif %}  {% if use_map %}  map_submit_search = function(){ -    var modal_base_text = $('.modal-progress .modal-header').html(); -    $('.modal-progress .modal-header').html("{% trans 'Fetching data...' %}"); -    $('.modal-progress').modal('show'); -    var data = search_get_query_data(query_vars, "{{name}}"); -    var nb_select = jQuery("#id_{{name}}-length_map").val(); -    if (!nb_select) nb_select = 10; - -    var url = "{{source}}json-map?length=" + nb_select + "&submited=1&" + data; -    var use_map_limit = false; -    if(data.indexOf("no_limit=true") == -1){ -        url += "&limit=" + current_map_limit; -        use_map_limit = true; -    } -    $.getJSON(url, function(data) { -        var timestamp = Math.floor(Date.now() / 1000); -        var map_id = "map-" + timestamp; -        $('.modal-progress .modal-header').html("{% trans 'Render map...' %}"); - -        var html = render_map(map_id, use_map_limit); -        $("#tab-content-map-{{name}}").html(html); -        $("#id_{{name}}-length_map").change(map_submit_search); -        if ($('.modal-progress').length > 0){ -            $('.modal-progress').modal('hide'); -            $('.modal-progress .modal-header').html(modal_base_text); -        } -        register_map(map_id, data); -    }); - -    return false; +    return _map_submit_search(query_vars, "{{name}}", "{{source}}");  };  {% endif %} +stats_submit_search = function(){ +    return _stats_submit_search(query_vars, "{{name}}", "{{source}}"); +};  datatable_submit_search = function(not_submited){      var data = search_get_query_data(query_vars, "{{name}}"); diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 145c56ca4..5b32a5fce 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1207,19 +1207,29 @@ def _get_data_from_query_old(items, query_table_cols, request,  def _get_json_stats(items, stats_sum_variable, stats_modality_1,                      stats_modality_2): -    q = items.values(stats_modality_1, stats_modality_2) +    if stats_modality_2: +        q = items.values(stats_modality_1, stats_modality_2) +    else: +        q = items.values(stats_modality_1)      if stats_sum_variable == 'pk':          q = q.annotate(sum=Count('pk'))      else:          q = q.annotate(sum=Sum(stats_sum_variable))      data = [] -    for values in q.order_by(stats_modality_1, stats_modality_2).all(): -        modality_1 = values[stats_modality_1] -        if not data or data[-1][0] != modality_1: -            data.append([modality_1, []]) -        data[-1][1].append( -            (values[stats_modality_2], values["sum"]) -        ) +    if stats_modality_2 and stats_modality_2 != stats_modality_1: +        q = q.order_by(stats_modality_1, stats_modality_2) +        for values in q.all(): +            modality_1 = values[stats_modality_1] +            if not data or data[-1][0] != modality_1: +                data.append([modality_1, []]) +            data[-1][1].append( +                (values[stats_modality_2], values["sum"]) +            ) +    else: +        q = q.order_by(stats_modality_1) +        for values in q.all(): +            modality_1 = values[stats_modality_1] +            data.append([modality_1, values["sum"]])      data = json.dumps({"data": data})      return HttpResponse(data, content_type='application/json') @@ -1634,9 +1644,8 @@ def get_item(model, func_name, default_name, extra_request_keys=None,              if not stats_modality_1 or \                      stats_modality_1 not in model.STATISTIC_MODALITIES:                  stats_modality_1 = model.STATISTIC_MODALITIES[0] -            if not stats_modality_2 or \ -                    stats_modality_2 not in model.STATISTIC_MODALITIES: -                stats_modality_2 = model.STATISTIC_MODALITIES[1] +            if stats_modality_2 not in model.STATISTIC_MODALITIES: +                stats_modality_2 = None              stats_sum_variable = request_items.get('stats_sum_variable', None)              stats_sum_variable_keys = list(model.STATISTIC_SUM_VARIABLE.keys())              if not stats_sum_variable or \ diff --git a/version.py b/version.py index 3fa515116..7111aa41b 100644 --- a/version.py +++ b/version.py @@ -1,5 +1,5 @@ -# 2.1.dev.39 -VERSION = (2, 1, 'dev', 39) +# 2.1.dev.40 +VERSION = (2, 1, 'dev', 40)  def get_version(): | 
