diff options
| -rw-r--r-- | ishtar_common/static/js/ishtar.js | 160 | ||||
| -rw-r--r-- | ishtar_common/templates/base.html | 3 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/DataTables.html | 158 | ||||
| -rw-r--r-- | ishtar_common/views_item.py | 15 | ||||
| -rw-r--r-- | scss/custom.scss | 18 | 
5 files changed, 291 insertions, 63 deletions
diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index ea0ccc516..a41b718a7 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -40,6 +40,7 @@ function get_previous_table_id(){}  var datatable_submit_search = function() {}; +var current_tab = "table";  var shortcut_url = '';  var show_shortcut_menu = false;  var alert_url = ''; @@ -48,6 +49,7 @@ var datatables_i18n;  var current_modal;  var default_search_vector;  var pin_search_url; +var static_path = '/static/';  var datatables_default = {      "processing": true, @@ -67,6 +69,8 @@ var datatables_static_default = {      "lengthMenu": [ 5, 10, 25, 50, 100 ]  }; +var show_msg = "Show"; +var entries_msg = "entries";  var activate_all_search_msg = "Searches in the shortcut menu deals with all items.";  var activate_own_search_msg = "Searches in the shortcut menu deals with only your items.";  var added_message = " items added."; @@ -979,3 +983,159 @@ var dt_multi_enable_disable_submit_button = function(e, dt, type, indexes){          $("#validation-bar #submit_form").prop('disabled', true);      }  }; + +var render_gallery = function(data_table, table_name, nb_select){ +    var html = '<label>' + show_msg; +    var id_select = table_name + '-length_image'; +    html += ' <select name="' + id_select + '" id="id_' + id_select + '">'; +    var nb_rows = [5, 10, 25, 50, 100]; +    for (idx in nb_rows){ +        var nb = nb_rows[idx]; +        html += '<option value="' + nb + '"'; +        if (nb == nb_select) html += " selected='selected'"; +        html += '>' + nb + '</option>'; +    } +    html += '</select> ' + entries_msg + '</label>'; +    html += "<div class='ishtar-gallery d-flex flex-wrap'>"; + +    $.each(data_table["rows"], function(idx, data){ +        var image = ""; +        if ("main_image__image" in data){ +            image = data["main_image__image"]; +        } else { +            image = static_path + "media/images/empty-image.png"; +        } +        var link = data["link"]; +        var name = ''; +        if ("cached_label" in data){ +            name = data["cached_label"]; +        } +        if ("name" in data){ +            name = data["name"]; +        } +        html += '<div class="card m-2">'; +        html += '<a class="thumb-image" href="#">'; +        html += '<img class="card-img-top" src="' + image + '">'; +        html += '</a>'; +        html += '<div class="card-body">'; +        html += '<h4 class="card-title">' + link + " " + name + '</h4>'; +        html += "</div></div>"; +    }); +    html += "</div>"; + +    /* pagination */ +    var page_total = data_table['total']; +    var page_current = data_table['page']; +    html += "<div class='dataTables_wrapper'><div class='dataTables_paginate'>"; +    html += '<ul class="image-pagination">'; + +    var disabled = page_current == 1; +    html += render_paginate_button(page_current - 1, page_current, "Previous", +                                   disabled, " previous"); +    html += render_paginate_button(1, page_current); + +    var idx_page = 2; +    if (page_current < 5){ +        while (idx_page <= 5){ +            if (idx_page <= page_total){ +                html += render_paginate_button(idx_page, page_current); +                idx_page += 1; +            } +        } +        if (page_total > 6){ +            html += render_paginate_button('...'); +        } +        html += render_paginate_button(page_total, page_current); +    } else { +        html += render_paginate_button('...'); +        if (page_total < page_current + 2 && +            page_total > (page_current - 2)){ +            html += render_paginate_button(page_current - 3, page_current); +        } +        if (page_total < page_current + 3 && +            page_total > (page_current - 3)){ +            html += render_paginate_button(page_current - 2, page_current); +        } +        html += render_paginate_button(page_current - 1, page_current); +        html += render_paginate_button(page_current, page_current); +        if (page_total > page_current) +            html += render_paginate_button(page_current + 1, page_current); +        if (page_total < page_current + 3){ +            idx_page = page_current + 2; +            while (idx_page <= page_total){ +                html += render_paginate_button(idx_page, page_current); +                idx_page += 1; +            } +        } else { +            html += render_paginate_button('...'); +            html += render_paginate_button(page_total, page_current); +        } +    } + +    disabled = page_current == page_total; +    html += render_paginate_button( +        page_current + 1, page_current, "Next", disabled, " next"); + +    html += '</ul></div></div>'; +    return html; +}; + +var render_paginate_button = function(nb, current, label, disabled, extra_class){ +    if (!extra_class) extra_class = ''; +    if (nb == '...'){ +        disabled = true; +    } else if (current == nb) { +        extra_class += ' active'; +    } +    if (disabled) extra_class += ' disabled'; +    if (!label) label = nb; + +    var html = '<li class="paginate_button page-item' + extra_class +'">'; +    html += '<a href="#" data-dt-idx="' + nb + '" tabindex="0" class="page-link">'; +    html += label + '</a></li>'; +    return html; +}; + +var current_image_page = 1; + +var register_image_paginate = function(){ +    $(".image-pagination .paginate_button a").click(function(){ +        current_image_page = $(this).attr('data-dt-idx'); +        gallery_submit_search(); +    }); +}; + +var main_submit_search = function(){ +    if (current_tab == "table") datatable_submit_search(); +    if (current_tab == "gallery") gallery_submit_search(); +}; + +var search_get_query_data = function(query_vars, table_name){ +    $("#id_search_vector").removeClass('input-progress'); +    if ($('.modal-progress').length > 0){ +        $('.modal-progress').modal('show'); +    } +    var data = ""; +    for (idx in query_vars){ +        var key = query_vars[idx]; +        var item = jQuery("#id_" + key); +        var val = null; +        if (item.prop('type') == 'checkbox'){ +            if (item.prop('checked')){ +                var val = item.val(); +            } +        } else { +            var val = item.val(); +        } +        if (val){ +            if (data) data += "&"; +            data += key + "=" + encodeURIComponent(val); +        } +    } +    if (current_image_page && current_tab == "gallery"){ +        var id_select = "#id_" + table_name + '-length_image'; +        if (data) data += "&"; +        data += "start=" + ((current_image_page - 1) * $(id_select).val()); +    } +    return data; +}; diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index e5af101d5..c84083409 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -30,6 +30,7 @@              src="{{STATIC_URL}}datatables/i18n/{{LANGUAGE_CODE}}.js?ver={{VERSION}}"></script>      {{EXTRA_JS|safe}}      <script type='text/javascript'> +    var static_path = "{{STATIC_URL}}";      var shortcut_url = '{% url "shortcut-menu" %}';      {% if DISPLAY_PIN_MENU %}var show_shortcut_menu = true;{% endif %}      var alert_url = '{% url "alert-list" %}'; @@ -47,6 +48,8 @@      var select_only_one_msg = "{% trans "Select only one item." %}";      var YES = "{% trans 'yes' %}";      var NO = "{% trans 'no' %}"; +    var show_msg = "{% trans "Show" %}"; +    var entries_msg = "{% trans "entries" %}";      var autorefresh_message_start = "{% trans 'Autorefresh start. The form is disabled.' %}";      var autorefresh_message_end =  "{% trans 'Autorefresh end. The form is re-enabled.' %}";      </script> diff --git a/ishtar_common/templates/blocks/DataTables.html b/ishtar_common/templates/blocks/DataTables.html index 096650115..07725353c 100644 --- a/ishtar_common/templates/blocks/DataTables.html +++ b/ishtar_common/templates/blocks/DataTables.html @@ -27,50 +27,79 @@    </div>  </div> -<div id="grid_{{name}}_meta_wrapper"> -    <table id='grid_{{name}}' class="display" width="100%"> -        <thead> -        <tr> -            <th></th> -            <th></th>{% for col in col_names %} -            <th>{{col}}</th> -        {% endfor %}</tr> -        </thead> -    </table> -</div> +<ul class="nav nav-tabs m-3"> +  <li class="nav-item"> +    <a class="nav-link active" id="tab-grid-{{name}}" data-toggle="tab" +       href="#tab-content-grid-{{name}}" role="tab" +       aria-controls="tab-content-grid-{{name}}" aria-selected="true"> +        {% trans "Table" %} +    </a> +  </li> +  <li class="nav-item"> +      <a class="nav-link" id="tab-gallery-{{name}}" data-toggle="tab" +         href="#tab-content-gallery-{{name}}" role="tab" +         aria-controls="tab-content-gallery-{{name}}" aria-selected="true"> +          {% trans "Gallery" %} +      </a> +  </li> +</ul> -<div id='foot_{{name}}' class="gridfooter row toolbar"> -    <div class='col-md-2'> -        <div class="btn-group btn-group-sm" role="group"> -            <button type='button' class="btn btn-secondary" data-toggle="modal" -                    data-target="#modal_grid_{{name}}"> -                {% trans "Expand table" %} <i class="fa fa-expand" aria-hidden="true"></i> -            </button> -        </div> + +<div class="tab-content"> +  <div class="tab-pane active" +       id="tab-content-grid-{{name}}" role="tabpanel" +       aria-labelledby="tab-grid-{{name}}"> + +    <div id="grid_{{name}}_meta_wrapper"> +        <table id='grid_{{name}}' class="display" width="100%"> +            <thead> +            <tr> +                <th></th> +                <th></th>{% for col in col_names %} +                <th>{{col}}</th> +            {% endfor %}</tr> +            </thead> +        </table>      </div> -    <div class='col-md-2'> -        <div class="btn-group btn-group-sm" role="group" -             aria-label="{% trans 'Export'%}"> -            {% if source_full or extra_sources %} -            <a class="btn btn-secondary" href='{{source}}csv' target='_blank' -               title="{% trans 'Export as CSV - ' %}{% trans 'simple'%}">{% trans "Simple CSV" %}</a> -            {% if source_full %}<a class='btn btn-secondary' href='{{source_full}}csv' target='_blank' title="{% trans 'Export as CSV - full' %}">{% trans "CSV full" %}</a>{% endif %} -            {% for slug, name, extra_source in extra_sources %} -            <a class="btn btn-secondary" href='{{extra_source}}csv' target='_blank' title="{% trans 'Export as CSV - ' %}{{name}}">{{name}}</a> -            {% endfor %} -            {% else %} -            <a class="btn btn-secondary" href="{{source}}csv" target="_blank" title="{% trans 'Export as CSV' %}">{% trans "CSV" %}</a> -            {% endif %} + +    <div id='foot_{{name}}' class="gridfooter row toolbar"> +        <div class='col-md-2'> +            <div class="btn-group btn-group-sm" role="group"> +                <button type='button' class="btn btn-secondary" data-toggle="modal" +                        data-target="#modal_grid_{{name}}"> +                    {% trans "Expand table" %} <i class="fa fa-expand" aria-hidden="true"></i> +                </button> +            </div> +        </div> +        <div class='col-md-2'> +            <div class="btn-group btn-group-sm" role="group" +                 aria-label="{% trans 'Export'%}"> +                {% if source_full or extra_sources %} +                <a class="btn btn-secondary" href='{{source}}csv' target='_blank' +                   title="{% trans 'Export as CSV - ' %}{% trans 'simple'%}">{% trans "Simple CSV" %}</a> +                {% if source_full %}<a class='btn btn-secondary' href='{{source_full}}csv' target='_blank' title="{% trans 'Export as CSV - full' %}">{% trans "CSV full" %}</a>{% endif %} +                {% for slug, name, extra_source in extra_sources %} +                <a class="btn btn-secondary" href='{{extra_source}}csv' target='_blank' title="{% trans 'Export as CSV - ' %}{{name}}">{{name}}</a> +                {% endfor %} +                {% else %} +                <a class="btn btn-secondary" href="{{source}}csv" target="_blank" title="{% trans 'Export as CSV' %}">{% trans "CSV" %}</a> +                {% endif %} +            </div>          </div>      </div> -</div> -{% if multiple %} -<input type="button" id="add_button_{{name}}" value="{% trans 'Add' %}"/> -<ul id="selectmulti_{{name}}" class="selectmulti"></ul> -{% endif %} +    {% if multiple %} +    <input type="button" id="add_button_{{name}}" value="{% trans 'Add' %}"/> +    <ul id="selectmulti_{{name}}" class="selectmulti"></ul> +    {% endif %} -<input type="hidden" id="hidden_{{name}}" name="{{name}}"/> +    <input type="hidden" id="hidden_{{name}}" name="{{name}}"/> +  </div> +  <div class="tab-pane active" +       id="tab-content-gallery-{{name}}" role="tabpanel" +       aria-labelledby="tab-gallery-{{name}}"> +  </div> +</div>  <script type="text/javascript" language='javascript'>  $('#modal_grid_{{name}}').on('show.bs.modal', function (e) { @@ -90,33 +119,41 @@ $('#modal_grid_{{name}}').on('hide.bs.modal', function (e) {      current_modal = null;  }); +$("#tab-gallery-{{name}}").click(function(){ +    current_tab = "gallery"; +    gallery_submit_search(); +}); + +$("#tab-grid-{{name}}").click(function(){ +    current_tab = "table"; +    datatable_submit_search(); +}); +  var query_vars = new Array({{col_idx|safe}});  var selItems_{{sname}} = new Array(); +gallery_submit_search = function(){ +    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) { +        $("#tab-content-gallery-{{name}}").html( +            render_gallery(data, "{{name}}", nb_select)); +        $("#id_{{name}}-length_image").change(gallery_submit_search); +        register_image_paginate(); +    }); -datatable_submit_search = function(){ -    $("#id_search_vector").removeClass('input-progress');      if ($('.modal-progress').length > 0){ -        $('.modal-progress').modal('show'); -    } -    var data = ""; -    for (idx in query_vars){ -        var key = query_vars[idx]; -        var item = jQuery("#id_"+key); -        var val = null; -        if (item.prop('type') == 'checkbox'){ -            if (item.prop('checked')){ -                var val = item.val(); -            } -        } else { -            var val = item.val(); -        } -        if (val){ -            if (data) data += "&"; -            data += key + "=" + encodeURIComponent(val); -        } +        $('.modal-progress').modal('hide');      } +    return false; +}; + +datatable_submit_search = function(){ +    var data = search_get_query_data(query_vars, "{{name}}");      var mygrid = jQuery("#grid_{{name}}");      var url = "{{source}}?submited=1&" + data;      datatable_{{sname}}.ajax.url(url).load(); @@ -134,8 +171,11 @@ datatable_submit_search = function(){      return false;  }; +  jQuery(document).ready(function(){ -  jQuery("#search_{{name}}").click(datatable_submit_search); +  jQuery("#search_{{name}}").click( +    main_submit_search +  );    var base_source = "{{source}}"; diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 6f4abdee9..dee4d2ffb 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1003,6 +1003,9 @@ def get_item(model, func_name, default_name, extra_request_keys=None,          if data_type == "json":              EMPTY = '[]' +        if data_type not in ('json', 'csv', 'json-image'): +            return HttpResponse(EMPTY, content_type='text/plain') +          model_to_check = model          if model_for_perms:              model_to_check = model_for_perms @@ -1301,13 +1304,16 @@ def get_item(model, func_name, default_name, extra_request_keys=None,                  if col in model.CONTEXTUAL_TABLE_COLS[contxt]:                      query_table_cols[idx] = \                          model.CONTEXTUAL_TABLE_COLS[contxt][col] -        if full == 'shortcut': +        if full == 'shortcut' or data_type == 'json-image':              if model.SLUG == "warehouse":                  query_table_cols = ['name']                  table_cols = ['name']              else:                  query_table_cols = ['cached_label']                  table_cols = ['cached_label'] +            if data_type == 'json-image': +                query_table_cols.append('main_image__image') +                table_cols.append('main_image__image')          # manage sort tables          manual_sort_key = None @@ -1371,7 +1377,7 @@ def get_item(model, func_name, default_name, extra_request_keys=None,          # pager management          start, end = 0, None          page_nb = 1 -        if row_nb and data_type == "json": +        if row_nb and data_type.startswith("json"):              try:                  start = int(request_items.get('start'))                  page_nb = start / row_nb + 1 @@ -1478,11 +1484,12 @@ def get_item(model, func_name, default_name, extra_request_keys=None,                          "onclick='load_window(\"%s\")'>" \                          "<i class=\"fa fa-info-circle\" aria-hidden=\"true\"></i></a>"          link_ext_template = '<a href="{}" target="_blank">{}</a>' -        if data_type == "json": +        if data_type.startswith("json"):              rows = []              for data in datas:                  try: -                    lnk = link_template % reverse('show-' + default_name, +                    lnk_template = link_template +                    lnk = lnk_template % reverse('show-' + default_name,                                                    args=[data[0], ''])                  except NoReverseMatch:                      logger.warning( diff --git a/scss/custom.scss b/scss/custom.scss index 56dbffab6..d0cbdc6eb 100644 --- a/scss/custom.scss +++ b/scss/custom.scss @@ -278,6 +278,10 @@ textarea {      background-color: $gray-400;  } +.form h4.card-title { +    background-color: transparent; +} +  .collapse-form .card,  .collapse-form .card-header{      border-radius: 0; @@ -521,6 +525,20 @@ ul.compact{      display: none;  } +.ishtar-gallery .card{ +    width: 200px; +} + +.thumb-image{ +    display: block; +    position:relative; +    overflow:hidden; +    padding-bottom:100%; +} +.thumb-image img{ +    position:absolute; +} +  /* lightgallery */  .lightgallery-captions{  | 
