diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2018-12-24 18:53:44 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-01-11 17:30:46 +0100 |
commit | 67ee211d9ec5eb81ea2e19b61772e396fe631820 (patch) | |
tree | d87e660e89a257cef067fa48d7cf4e28c1fe8001 | |
parent | 57fa3f4525fb3ffaac6f061fcbc9f586a82968a6 (diff) | |
download | Ishtar-67ee211d9ec5eb81ea2e19b61772e396fe631820.tar.bz2 Ishtar-67ee211d9ec5eb81ea2e19b61772e396fe631820.zip |
Image gallery on tables first version
-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{ |