diff options
-rw-r--r-- | archaeological_context_records/urls.py | 3 | ||||
-rw-r--r-- | archaeological_context_records/views.py | 1 | ||||
-rw-r--r-- | archaeological_files/urls.py | 3 | ||||
-rw-r--r-- | archaeological_files/views.py | 1 | ||||
-rw-r--r-- | archaeological_finds/urls.py | 3 | ||||
-rw-r--r-- | archaeological_finds/views.py | 1 | ||||
-rw-r--r-- | archaeological_operations/urls.py | 7 | ||||
-rw-r--r-- | archaeological_operations/views.py | 1 | ||||
-rw-r--r-- | ishtar_common/static/js/ishtar.js | 66 | ||||
-rw-r--r-- | ishtar_common/static/media/style.css | 32 | ||||
-rw-r--r-- | ishtar_common/templates/base.html | 10 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/blocks/shortcut_menu.html | 24 | ||||
-rw-r--r-- | ishtar_common/urls.py | 4 | ||||
-rw-r--r-- | ishtar_common/views.py | 107 |
14 files changed, 189 insertions, 74 deletions
diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py index 8e218102d..a25559e29 100644 --- a/archaeological_context_records/urls.py +++ b/archaeological_context_records/urls.py @@ -89,6 +89,9 @@ urlpatterns += patterns( url(r'get-contextrecord-full/(?P<type>.+)?$', 'get_contextrecord', name='get-contextrecord-full', kwargs={'full': True}), + url(r'get-contextrecord-shortcut/(?P<type>.+)?$', + 'get_contextrecord', name='get-contextrecord-shortcut', + kwargs={'full': 'shortcut'}), url(r'show-contextrecordsource(?:/(?P<pk>.+))?/(?P<type>.+)?$', 'show_contextrecordsource', name=models.ContextRecordSource.SHOW_URL), url(r'get-contexrecordsource/(?P<type>.+)?$', diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 5c8bb63cc..bc95473e6 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -46,6 +46,7 @@ contextrecord_extra_keys = { 'parcel_2': 'operation__parcels__public_domain', 'label': 'label__icontains', 'archaeological_sites': 'operation__archaeological_sites__pk', + 'cached_label': 'cached_label__icontains', } diff --git a/archaeological_files/urls.py b/archaeological_files/urls.py index c6b932fec..b762a54b3 100644 --- a/archaeological_files/urls.py +++ b/archaeological_files/urls.py @@ -75,6 +75,9 @@ urlpatterns += patterns( name='get-file'), url(r'get-file-full/(?P<type>.+)?$', 'get_file', name='get-file-full', kwargs={'full': True}), + url(r'get-file-shortcut/(?P<type>.+)?$', + 'get_file', name='get-file-shortcut', + kwargs={'full': 'shortcut'}), url(r'get-administrativeactfile/(?P<type>.+)?$', 'get_administrativeactfile', name='get-administrativeactfile'), url(r'show-file(?:/(?P<pk>.+))?/(?P<type>.+)?$', 'show_file', diff --git a/archaeological_files/views.py b/archaeological_files/views.py index e457c2ce7..a8053214f 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -91,6 +91,7 @@ get_file = get_item( 'towns__numero_insee__startswith': 'towns__numero_insee__startswith', 'name': 'name__icontains', + 'cached_label': 'cached_label__icontains', 'comment': 'comment__icontains', 'permit_reference': 'permit_reference__icontains', 'general_contractor__attached_to': diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 63bc01bed..17cc4028f 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -119,6 +119,9 @@ urlpatterns += patterns( name='get-own-find-full', kwargs={'full': True, 'force_own': True}), url(r'get-find-full/(?P<type>.+)?$', 'get_find', name='get-find-full', kwargs={'full': True}), + url(r'get-find-shortcut/(?P<type>.+)?$', + 'get_find', name='get-find-shortcut', + kwargs={'full': 'shortcut'}), url(r'get-findsource/(?P<type>.+)?$', 'get_findsource', name='get-findsource'), url(r'get-findsource-full/(?P<type>.+)?$', diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 80cc6fd8c..d441559cc 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -64,6 +64,7 @@ find_extra_keys = { 'base_finds__find__description__icontains', 'base_finds__batch': 'base_finds__batch', 'basket': 'basket', + 'cached_label': 'cached_label__icontains', 'image': 'image__isnull'} get_find = get_item( diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py index 7d494f973..aca98d4c4 100644 --- a/archaeological_operations/urls.py +++ b/archaeological_operations/urls.py @@ -100,11 +100,14 @@ urlpatterns += patterns( kwargs={'force_own': True}), url(r'get-operation/(?P<type>.+)?$', 'get_operation', name='get-operation'), - url(r'get-operation-full/(?P<type>.+)?$', 'get_operation', - name='get-operation-full', kwargs={'full': True}), url(r'get-operation-full/own/(?P<type>.+)?$', 'get_operation', name='get-own-operation-full', kwargs={'full': True, 'force_own': True}), + url(r'get-operation-full/(?P<type>.+)?$', 'get_operation', + name='get-operation-full', kwargs={'full': True}), + url(r'get-operation-shortcut/(?P<type>.+)?$', + 'get_operation', name='get-operation-shortcut', + kwargs={'full': 'shortcut'}), url(r'get-available-operation-code/(?P<year>.+)?$', 'get_available_operation_code', name='get_available_operation_code'), url(r'revert-operation/(?P<pk>.+)/(?P<date>.+)$', diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index 84e98010e..ae82e9e89 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -148,6 +148,7 @@ get_operation = get_item( relative_session_names=[('file', 'associated_file__pk')], extra_request_keys={ 'common_name': 'common_name__icontains', + 'cached_label': 'cached_label__icontains', 'comment': 'comment__icontains', 'scientific_documentation_comment': 'scientific_documentation_comment__icontains', diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index fecefe0a9..9021dc4f5 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -23,8 +23,6 @@ beforeSend: function(xhr, settings) { } }}); -var shortcut_url = ''; - function manage_async_link(event){ event.preventDefault(); var url = $(this).attr('href'); @@ -38,36 +36,53 @@ function manage_async_link(event){ function get_next_table_id(){} function get_previous_table_id(){} -function init_shortcut_menu(html){ - $("#progress").hide(); - $("#context_menu").html(html); - $(".chosen-select").chosen(); - $("#current_file").change(function(){ +var shortcut_url = ''; +var activate_all_search_url = '/activate-all-search/'; +var activate_own_search_url = '/activate-own-search/'; + + +function init_shortcut_fields(){ + $('#id_file-shortcut').change(function(){ + $("#id_select_file-shortcut").attr( + 'title', $('#id_select_file-shortcut').val()); $.post('/' + url_path + 'update-current-item/', - {item:'file', value:$("#current_file").val()}, + {item: "file", value:$("#id_file-shortcut").val()}, load_shortcut_menu ); }); - $("#current_operation").change(function(){ + $('#id_operation-shortcut').change(function(){ + $("#id_select_operation-shortcut").attr( + 'title', $('#id_select_operation-shortcut').val()); $.post('/' + url_path + 'update-current-item/', - {item:'operation', value:$("#current_operation").val()}, + {item: "operation", value:$("#id_operation-shortcut").val()}, load_shortcut_menu ); }); - $("#current_contextrecord").change(function(){ + $('#id_contextrecord-shortcut').change(function(){ + $("#id_select_contextrecord-shortcut").attr( + 'title', $('#id_select_contextrecord-shortcut').val()); $.post('/' + url_path + 'update-current-item/', - {item:'contextrecord', value:$("#current_contextrecord").val()}, + {item: "contextrecord", value:$("#id_contextrecord-shortcut").val()}, load_shortcut_menu ); }); - $("#current_find").change(function(){ + $('#id_find-shortcut').change(function(){ + $("#id_select_find-shortcut").attr( + 'title', $('#id_select_find-shortcut').val()); $.post('/' + url_path + 'update-current-item/', - {item:'find', value:$("#current_find").val()}, + {item: "find", value:$("#id_find-shortcut").val()}, load_shortcut_menu ); }); } +function init_shortcut_menu(html){ + $("#progress").hide(); + $("#context_menu").html(html); + $(".chosen-select").chosen(); + init_shortcut_fields(); +} + function display_info(msg){ $('#message .information .content').html(msg); $('#message').fadeIn('slow'); @@ -191,7 +206,7 @@ function load_window(url, speed, on_success){ } function load_current_window(url, model_name){ - var id = $("#current_" + model_name).val(); + var id = $("#id_" + model_name + "-shortcut").val(); if (!id) return; url = url.split('/'); url[url.length - 1] = id; @@ -267,3 +282,24 @@ function show_hide_flex(id){ $(id).hide(); } } + +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."; + +function activate_all_search(){ + $('.activate_all_search').removeClass('disabled'); + $('.activate_own_search').addClass('disabled'); + $.get(activate_all_search_url, function(data) { + display_info(activate_all_search_msg); + }); + return false; +} + +function activate_own_search(){ + $('.activate_own_search').removeClass('disabled'); + $('.activate_all_search').addClass('disabled'); + $.get(activate_own_search_url, function(data) { + display_info(activate_own_search_msg); + }); + return false; +} diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css index aab5063e4..fff2fad78 100644 --- a/ishtar_common/static/media/style.css +++ b/ishtar_common/static/media/style.css @@ -29,6 +29,16 @@ a, a.remove { color:#D14; } +span.disabled, +a.disabled { + color:#ccc; +} + +span.disabled:hover, +a.disabled:hover { + color:#DB5C7C; +} + .badge, a.add-button, #reset_wizards, @@ -56,6 +66,10 @@ a.add-button, font-family: 'FontAwesome', Arial, Helvetica, sans-serif; } +#context_menu .chosen-select{ + width: 400px; +} + #context_menu option.basket{ color:#000; } @@ -425,13 +439,25 @@ div#context_menu fieldset{ border-radius: 0; } +div#action_current_items{ + display: inline-block; + vertical-align: top; + width: 70px; +} + +div#action_current_items p{ + padding: 0; + margin: 0; + text-align: center; +} + div#context_menu table{ display: inline; vertical-align: top; } div#context_menu .icon{ - padding: 0.6em 0.5em; + padding: 0.2em 0.3em; } div#context_menu ul{ @@ -792,7 +818,9 @@ table.confirm tr.spacer td:last-child{ /* jquery widget customizations */ .ui-autocomplete{ - font-size:0.7em + font-size:0.7em; + z-index:10000 !important; + width:350px; } .ui-autocomplete-loading { diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 695edd758..7101ed7de 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -32,6 +32,14 @@ {% endblock %} <script type='text/javascript'> var shortcut_url = '{% url "shortcut-menu" %}'; + var get_file_url = '{% url "get-file-shortcut" %}'; + var get_operation_url = '{% url "get-operation-shortcut" %}'; + var get_contextrecord_url = '{% url "get-contextrecord-shortcut" %}'; + var get_find_url = '{% url "get-find-shortcut" %}'; + var activate_all_search_url = '{% url "activate-all-search" %}'; + var activate_own_search_url = '{% url "activate-own-search" %}'; + var activate_all_search_msg = "{% trans 'Searches in the shortcut menu deals with all items.' %}"; + var activate_own_search_msg = "{% trans 'Searches in the shortcut menu deals with only your items.' %}"; </script> </head> <body{% if current_theme%} id='{{current_theme}}'{%endif%}> @@ -50,7 +58,7 @@ {% csrf_token %} <label for='language_selector'>{% trans "Lang" %}{% trans ":"%} </label> <select name="language" id='language_selector'> - <option value="">-------</option> + <option value="">----------</option> {% for lang in LANGUAGES %} <option value="{{ lang.0 }}"{% ifequal LANGUAGE_CODE lang.0 %} selected='selected'{% endifequal %}>{{ lang.1 }}</option> {% endfor %} diff --git a/ishtar_common/templates/ishtar/blocks/shortcut_menu.html b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html index c1100ae01..fc1131c90 100644 --- a/ishtar_common/templates/ishtar/blocks/shortcut_menu.html +++ b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html @@ -1,21 +1,27 @@ {% load i18n %} {% load url from future%} -{% if current_menu %} +{% if menu %} <form method="post" action="{% url 'update-current-item' %}"> <fieldset> -<i class="icon fa fa-thumb-tack fa-2x" aria-hidden="true" title="{% trans 'Pin an item in order to constrain default searches with this item. By default only your items are displayed. New created and modified items are auto-pin.' %}"></i> +<div id='action_current_items'> +<p><i class="icon fa fa-thumb-tack fa-2x" aria-hidden="true" title="{% trans 'Pin an item in order to constrain default searches with this item. By default only your items are displayed. New created and modified items are auto-pin.' %}"></i></p> +<p> +<a href='' onclick='return activate_own_search();' class='activate_own_search{% if SHORTCUT_SEARCH == 'all' %} disabled{% endif %}'><i class="icon fa fa-user" aria-hidden="true" title="{% trans 'Search within my items' %}"></i></a> +<a href='' class='activate_all_search{% if SHORTCUT_SEARCH == 'own' %} disabled{% endif %}' onclick='return activate_all_search();'><i class="icon fa fa-users" aria-hidden="true" title="{% trans 'Search within all items' %}"></i></a> +</p> +<p> +<a href='' onclick='return load_shortcut_menu();' class='disabled'><i class="icon fa fa-2x fa-refresh" aria-hidden="true" title="{% trans 'Refresh menu' %}"></i></a> +</p> +</div> <table id='current_items'> -{% for lbl, model_name, main_cls, items in current_menu %} +{% for lbl, model_name, current, widget in menu %} <tr> <td><label for="current_{{model_name}}">{{lbl}}</label></td> <td> - <select class='{{main_cls}} chosen-select' id='current_{{model_name}}'> - <option class='normal' value=''>--</option> - {% for val, label, selected, cls in items %}<option{% if cls %} class='{{cls}}'{% endif %} value='{{val}}'{% if selected %} selected="selected"{% endif %}>{% ifequal cls 'basket' %} {% endifequal %}{% ifequal cls 'green' %} {% endifequal %}{% ifequal cls 'orange' %} {% endifequal %}{% ifequal cls 'red' %} {% endifequal %}{{label}}</option> - {% endfor %}</select> + {{widget|safe}} </td>{% with 'show-'|add:model_name as model_url%} - <td><a href='#' onclick='load_current_window("{% url model_url 0 %}", "{{model_name}}");' class='display_details'><i class="fa fa-info-circle" aria-hidden="true"></i></a></td> - <td><span class='pin-action' onclick='$.get("{% url 'unpin' model_name %}", function(){load_shortcut_menu();});' title="{% trans 'Unpin' %}"> + <td><a href='#' onclick='load_current_window("{% url model_url current %}", "{{model_name}}");' class='display_details'><i class="fa fa-info-circle" aria-hidden="true"></i></a></td> + <td><span class='disabled pin-action' onclick='$.get("{% url 'unpin' model_name %}", function(){load_shortcut_menu();});' title="{% trans 'Unpin' %}"> <i class="fa fa-times"></i> </span></td> {% endwith %} diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index 27078dd9e..5d8d25843 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -192,6 +192,10 @@ urlpatterns += patterns( views.OrgaManualMergeItems.as_view(), name='orga_manual_merge_items'), url(r'reset/$', 'reset_wizards', name='reset_wizards'), + url(r'activate-all-search/$', 'activate_all_search', + name='activate-all-search'), + url(r'activate-own-search/$', 'activate_own_search', + name='activate-own-search'), url(r'(?P<action_slug>' + actions + r')/$', 'action', name='action'), ) diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 5f3e80c77..67b883447 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -55,6 +55,7 @@ from xhtml2odt import xhtml2odt from menus import menu from archaeological_files.models import File +from archaeological_operations.models import Operation from archaeological_context_records.models import ContextRecord from archaeological_finds.models import Find @@ -62,7 +63,8 @@ from archaeological_operations.forms import DashboardForm as DashboardFormOpe from archaeological_files.forms import DashboardForm as DashboardFormFile from ishtar_common.forms import FinalForm, FinalDeleteForm -from ishtar_common.utils import get_random_item_image_link, shortify +from ishtar_common.widgets import JQueryAutoComplete +from ishtar_common.utils import get_random_item_image_link from ishtar_common import forms_common as forms from ishtar_common import wizards from ishtar_common.models import HistoryError, PRIVATE_FIELDS, \ @@ -198,12 +200,17 @@ def get_autocomplete_generic(model, extra={'available': True}): return func -def shortcut_menu(request): - from archaeological_operations.models import Operation - from archaeological_files.models import File - from archaeological_context_records.models import ContextRecord - from archaeological_finds.models import Find +def activate_all_search(request): + request.session['SHORTCUT_SEARCH'] = 'all' + return HttpResponse('OK', mimetype='text/plain') + + +def activate_own_search(request): + request.session['SHORTCUT_SEARCH'] = 'own' + return HttpResponse('OK', mimetype='text/plain') + +def shortcut_menu(request): profile = get_current_profile() CURRENT_ITEMS = [] if profile.files: @@ -213,46 +220,24 @@ def shortcut_menu(request): CURRENT_ITEMS.append((_(u"Context record"), ContextRecord)) if profile.find: CURRENT_ITEMS.append((_(u"Find"), Find)) - dct = {'current_menu': []} - current_selected_item = None + dct = {'current_menu': [], 'menu': [], + 'SHORTCUT_SEARCH': request.session['SHORTCUT_SEARCH'] + if 'SHORTCUT_SEARCH' in request.session else 'own'} + for lbl, model in CURRENT_ITEMS: - new_selected_item = None model_name = model.SLUG - cls = '' current = model_name in request.session and request.session[model_name] - items = [] - for item in model.get_owns(request.user, - menu_filtr=current_selected_item): - pk = unicode(item.pk) - if item.IS_BASKET: - pk = "basket-" + pk - selected = pk == current - if selected: - cls = item.get_short_menu_class() - new_selected_item = item - items.append((pk, shortify(unicode(item), 60), - selected, item.get_short_menu_class())) - # selected is not in owns - add it to the list - if not new_selected_item and current: - try: - item = model.objects.get(pk=int(current)) - new_selected_item = item - items.append((item.pk, shortify(unicode(item), 60), - True, item.get_short_menu_class())) - except (model.DoesNotExist, ValueError): - pass - if items: - dct['current_menu'].append((lbl, model_name, cls, items)) - current_selected_item = new_selected_item + + dct['menu'].append((lbl, model_name, current or 0, JQueryAutoComplete( + reverse('get-' + model.SLUG + '-shortcut'), + model).render( + model.SLUG + '-shortcut', value=current, + attrs={'id': 'current_' + model.SLUG}))) return render_to_response('ishtar/blocks/shortcut_menu.html', dct, context_instance=RequestContext(request)) def get_current_items(request): - from archaeological_files.models import File - from archaeological_operations.models import Operation - from archaeological_context_records.models import ContextRecord - from archaeological_finds.models import Find currents = {} for key, model in (('file', File), ('operation', Operation), @@ -290,6 +275,7 @@ def update_current_item(request, item_type=None, pk=None): request.session[item_type] = request.POST['value'] else: request.session[item_type] = str(pk) + request.session['SHORTCUT_SEARCH'] = 'all' currents = get_current_items(request) # reinit when descending item are not relevant @@ -516,6 +502,9 @@ def get_item(model, func_name, default_name, extra_request_keys=[], break # max right reach if force_own: own = True + if full == 'shortcut' and 'SHORTCUT_SEARCH' in request.session and \ + request.session['SHORTCUT_SEARCH'] == 'own': + own = True EMPTY = '' if 'type' in dct: data_type = dct.pop('type') @@ -544,6 +533,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], request_items = request.method == 'POST' and request.POST \ or request.GET dct = base_request.copy() + if full == 'shortcut': + dct['cached_label__icontains'] = request.GET.get('term', None) and_reqs, or_reqs = [], [] try: old = 'old' in request_items and int(request_items['old']) @@ -577,7 +568,7 @@ def get_item(model, func_name, default_name, extra_request_keys=[], q = Q(**{req_key: val}) reqs = reqs | q and_reqs.append(reqs) - if 'submited' not in request_items: + if 'submited' not in request_items and full != 'shortcut': # default search # an item is selected in the default menu if default_name in request.session and \ @@ -706,6 +697,22 @@ def get_item(model, func_name, default_name, extra_request_keys=[], for and_req in and_reqs: query = query & and_req + # manage hierarchic in shortcut menu + if full == 'shortcut': + ASSOCIATED_ITEMS = { + Operation: (File, 'associated_file__pk'), + ContextRecord: (Operation, 'operation__pk'), + Find: (ContextRecord, 'base_finds__context_record__pk'), + } + if model in ASSOCIATED_ITEMS: + upper_model, upper_key = ASSOCIATED_ITEMS[model] + model_name = upper_model.SLUG + current = model_name in request.session \ + and request.session[model_name] + if current: + dct = {upper_key: current} + query = query & Q(**dct) + items = model.objects.filter(query).distinct() # print(items.query) q = request_items.get('sidx') @@ -731,6 +738,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], for idx, col in enumerate(table_cols): if col in model.CONTEXTUAL_TABLE_COLS[contxt]: table_cols[idx] = model.CONTEXTUAL_TABLE_COLS[contxt][col] + if full == 'shortcut': + table_cols = ['cached_label'] # manage sort tables manual_sort_key = None @@ -773,6 +782,9 @@ def get_item(model, func_name, default_name, extra_request_keys=[], pass start = (page_nb - 1) * row_nb end = page_nb * row_nb + if full == 'shortcut': + start = 0 + end = 20 items_nb = items.count() if manual_sort_key: items = items.all() @@ -887,13 +899,18 @@ def get_item(model, func_name, default_name, extra_request_keys=[], if hasattr(model, 'COL_LINK') and k in model.COL_LINK: value = link_ext_template.format(value, value) res[k] = value + if full == 'shortcut': + res['value'] = res.pop('cached_label') rows.append(res) - data = json.dumps({ - "records": items_nb, - "rows": rows, - "page": page_nb, - "total": (items_nb / row_nb + 1) if row_nb else items_nb, - }) + if full == 'shortcut': + data = json.dumps(rows) + else: + data = json.dumps({ + "records": items_nb, + "rows": rows, + "page": page_nb, + "total": (items_nb / row_nb + 1) if row_nb else items_nb, + }) return HttpResponse(data, mimetype='text/plain') elif data_type == "csv": response = HttpResponse(mimetype='text/csv') |