From 5230a8e0a06a5d67d6c13f2359bc51be07b4fb5a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 9 Sep 2016 00:41:57 +0200 Subject: Shortcut menu: menu is now dynamic - selected items filter dependant items (refs #2996) - can now pin items from sheet (refs #3078) --- ishtar_common/views.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 6 deletions(-) (limited to 'ishtar_common/views.py') diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 46a8ceb6a..5022aa08e 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -62,7 +62,7 @@ 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 +from ishtar_common.utils import get_random_item_image_link, shortify from ishtar_common import forms_common as forms from ishtar_common import wizards from ishtar_common.models import HistoryError, PRIVATE_FIELDS, \ @@ -198,11 +198,122 @@ def get_autocomplete_generic(model, extra={'available': True}): return func -def update_current_item(request): - if not request.is_ajax() and not request.method == 'POST': - raise Http404 - if 'value' in request.POST and 'item' in request.POST: - request.session[request.POST['item']] = request.POST['value'] +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 + + profile = get_current_profile() + CURRENT_ITEMS = [] + if profile.files: + CURRENT_ITEMS.append((_(u"Archaeological file"), File)) + CURRENT_ITEMS.append((_(u"Operation"), Operation)) + if profile.context_record: + CURRENT_ITEMS.append((_(u"Context record"), ContextRecord)) + if profile.find: + CURRENT_ITEMS.append((_(u"Find"), Find)) + dct = {'current_menu': []} + current_selected_item = None + 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)) + 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 + 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), + ('contextrecord', ContextRecord), + ('find', Find)): + currents[key] = None + if key in request.session and request.session[key]: + try: + currents[key] = model.objects.get(pk=int(request.session[key])) + except (ValueError, File.DoesNotExist): + continue + return currents + + +def update_current_item(request, item_type=None, pk=None): + if not item_type or not pk: + if not request.is_ajax() and not request.method == 'POST': + raise Http404 + item_type = request.POST['item'] + if 'value' in request.POST and 'item' in request.POST: + request.session[item_type] = request.POST['value'] + else: + request.session[item_type] = str(pk) + + currents = get_current_items(request) + # reinit when descending item are not relevant + if item_type == 'file' and currents['file'] and currents['operation'] and \ + currents['operation'].associated_file != currents['file']: + request.session["operation"] = '' + currents['operation'] = None + if item_type in ('operation', 'file') and currents['contextrecord'] and \ + (not request.session["operation"] or + currents['contextrecord'].operation != currents['operation']): + request.session["contextrecord"] = '' + currents['contextrecord'] = None + from archaeological_finds.models import Find + if item_type in ('contextrecord', 'operation', 'file') and currents['find'] and\ + (not request.session["contextrecord"] or + not Find.objects.filter( + downstream_treatment__isnull=True, + base_finds__context_record__pk=request.session["contextrecord"], + pk=currents['find'].pk).count()): + request.session["find"] = '' + currents['find'] = None + + # re-init ascending item with relevant values + if item_type == "find" and currents['find']: + from archaeological_context_records.models import ContextRecord + q = ContextRecord.objects.filter( + base_finds__find__pk=currents['find'].pk) + if q.count(): + currents['contextrecord'] = q.all()[0] + request.session['contextrecord'] = str( + currents['contextrecord'].pk) + if item_type in ("find", 'contextrecord') and currents['contextrecord']: + currents['operation'] = currents['contextrecord'].operation + request.session['operation'] = str(currents['operation'].pk) + if item_type in ("find", 'contextrecord', 'operation') and \ + currents['operation']: + currents['file'] = currents['operation'].associated_file + request.session['file'] = str(currents['file'].pk) if currents['file'] \ + else None return HttpResponse('ok') -- cgit v1.2.3 From 916920ad3dcc18c2c252698ee192c265743ab01a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 9 Sep 2016 14:32:28 +0200 Subject: Shortcut menu: show all dependent items of pinned but not own parent item --- archaeological_context_records/models.py | 6 +++--- archaeological_finds/models.py | 6 +++--- archaeological_operations/models.py | 7 ++++--- ishtar_common/models.py | 8 ++++---- ishtar_common/views.py | 1 + 5 files changed, 15 insertions(+), 13 deletions(-) (limited to 'ishtar_common/views.py') diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index d4e175d55..0123dd2ed 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -227,11 +227,11 @@ class ContextRecord(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): @classmethod def get_owns(cls, user, menu_filtr=None): - extra_query = {} + replace_query = {} if menu_filtr: - extra_query = {'operation': menu_filtr} + replace_query = {'operation': menu_filtr} owns = super(ContextRecord, cls).get_owns(user, - extra_query=extra_query) + replace_query=replace_query) return sorted(owns, key=lambda x: x.cached_label) def full_label(self): diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index d266bba76..603e046ee 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -575,10 +575,10 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): @classmethod def get_owns(cls, user, menu_filtr=None): - extra_query = {} + replace_query = {} if menu_filtr: - extra_query = {'base_finds__context_record': menu_filtr} - owns = super(Find, cls).get_owns(user, extra_query=extra_query) + replace_query = {'base_finds__context_record': menu_filtr} + owns = super(Find, cls).get_owns(user, replace_query=replace_query) return sorted(owns, key=lambda x: x.cached_label) def _generate_cached_label(self): diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 701ae4593..228e9859e 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -300,10 +300,11 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, @classmethod def get_owns(cls, user, menu_filtr=None): - extra_query = {} + replace_query = {} if menu_filtr: - extra_query = {'associated_file': menu_filtr} - owns = super(Operation, cls).get_owns(user, extra_query=extra_query) + replace_query = {'associated_file': menu_filtr} + owns = super(Operation, cls).get_owns( + user, replace_query=replace_query) # owns = owns.annotate(null_count=Count('operation_code')) # return owns.order_by("common_name", "-year", "operation_code") return sorted(owns, key=lambda x: x.cached_label) diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 9e48df8d2..29dedd113 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -235,7 +235,7 @@ class OwnPerms: return cls.objects.filter(query).count() @classmethod - def get_owns(cls, user, extra_query={}): + def get_owns(cls, user, replace_query={}): """ Get Own items """ @@ -247,11 +247,11 @@ class OwnPerms: if hasattr(cls, 'BASKET_MODEL'): items = list(cls.BASKET_MODEL.objects.filter(user=user).all()) query = cls.get_query_owns(user) - if not query: + if not query and not replace_query: return cls.objects.filter(pk__isnull=True) q = cls.objects.filter(query) - if extra_query: - q = q.filter(**extra_query) + if replace_query: + q = cls.objects.filter(**replace_query) items += list(q.order_by(*cls._meta.ordering).all()) return items diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 5022aa08e..95c4dbd76 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -236,6 +236,7 @@ def shortcut_menu(request): 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): -- cgit v1.2.3 From 2a0b5e96a92202c9e16991584bb67e0c97e03edc Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 9 Sep 2016 16:42:37 +0200 Subject: Unpin item. --- ishtar_common/templates/ishtar/blocks/shortcut_menu.html | 3 +++ ishtar_common/urls.py | 1 + ishtar_common/views.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+) (limited to 'ishtar_common/views.py') diff --git a/ishtar_common/templates/ishtar/blocks/shortcut_menu.html b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html index 29c975e79..c1100ae01 100644 --- a/ishtar_common/templates/ishtar/blocks/shortcut_menu.html +++ b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html @@ -15,6 +15,9 @@ {% endfor %} {% with 'show-'|add:model_name as model_url%} + + + {% endwith %} {% endfor %} diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index 802e6ca0d..049bcaf7b 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -132,6 +132,7 @@ urlpatterns += patterns( name='update-current-item'), url(r'pin/(?P[a-z-]+)/(?P\d+)/$', 'update_current_item', name='pin'), + url(r'unpin/(?P[a-z-]+)/$', 'unpin', name='unpin'), url(r'new-person/(?:(?P[^/]+)/)?(?:(?P[^/]+)/)?$', 'new_person', name='new-person'), url(r'new-person-noorga/' diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 95c4dbd76..50c647372 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -267,6 +267,20 @@ def get_current_items(request): return currents +def unpin(request, item_type): + request.session['find'] = '' + if item_type == 'find': + return HttpResponse('ok') + request.session['contextrecord'] = '' + if item_type == 'contextrecord': + return HttpResponse('ok') + request.session['operation'] = '' + if item_type == 'operation': + return HttpResponse('ok') + request.session['file'] = '' + return HttpResponse('ok') + + def update_current_item(request, item_type=None, pk=None): if not item_type or not pk: if not request.is_ajax() and not request.method == 'POST': -- cgit v1.2.3 From 6ee8c39a2e8e053810bea643fdf0f8c3fa21374b Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 9 Sep 2016 19:31:14 +0200 Subject: Shortcut menu: parent items constraint default search if no default item is set (refs #1318) --- archaeological_context_records/views.py | 7 +++++++ archaeological_files/views.py | 2 +- archaeological_finds/views.py | 12 ++++++++++++ archaeological_operations/views.py | 3 ++- ishtar_common/views.py | 10 ++++++---- 5 files changed, 28 insertions(+), 6 deletions(-) (limited to 'ishtar_common/views.py') diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 4fd945187..5c8bb63cc 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -81,6 +81,9 @@ get_contextrecord = get_item( models.ContextRecord, 'get_contextrecord', 'contextrecord', relation_types_prefix={'ope_relation_types': 'operation__'}, + relative_session_names=[ + ('operation', 'operation__pk'), + ('file', 'operation__associated_file__pk')], extra_request_keys=contextrecord_extra_keys,) get_contextrecord_for_ope = get_item( models.ContextRecord, @@ -94,6 +97,10 @@ show_contextrecordsource = show_item(models.ContextRecordSource, get_contextrecordsource = get_item( models.ContextRecordSource, 'get_contextrecordsource', 'contextrecordsource', + relative_session_names=[ + ('contextrecord', 'context_record__pk'), + ('operation', 'context_record__operation__pk'), + ('file', 'context_record__operation__associated_file__pk')], bool_fields=['duplicate'], extra_request_keys={ 'title': 'title__icontains', diff --git a/archaeological_files/views.py b/archaeological_files/views.py index 7e96c33d3..e457c2ce7 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -143,7 +143,7 @@ get_administrativeactfile = get_item( 'associated_file__permit_reference__icontains'}, reversed_bool_fields=['index__isnull'], base_request={"associated_file__pk__isnull": False}, - relative_session_names={'file': 'associated_file__pk'}) + relative_session_names=[('file', 'associated_file__pk')]) def dashboard_file(request, *args, **kwargs): diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 57b2b7665..80cc6fd8c 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -72,6 +72,11 @@ get_find = get_item( relation_types_prefix={ 'ope_relation_types': 'base_finds__context_record__operation__'}, + relative_session_names=[ + ('contextrecord', 'base_finds__context_record__pk'), + ('operation', 'base_finds__context_record__operation__pk'), + ('file', 'base_finds__context_record__operation__associated_file__pk') + ], base_request={'downstream_treatment__isnull': True}, extra_request_keys=find_extra_keys.copy()) @@ -87,6 +92,13 @@ show_findsource = show_item(models.FindSource, 'findsource') get_findsource = get_item( models.FindSource, 'get_findsource', 'findsource', bool_fields=['duplicate'], + relative_session_names=[ + ('find', 'find__pk'), + ('contextrecord', 'find__base_finds__context_record__pk'), + ('operation', 'find__base_finds__context_record__operation__pk'), + ('file', + 'find__base_finds__context_record__operation__associated_file__pk') + ], extra_request_keys={ 'title': 'title__icontains', 'description': 'description__icontains', diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index b47623fc2..6c7fdbd98 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -145,6 +145,7 @@ get_operation = get_item( 'documentation_deadline__lte', 'documentation_deadline__gte', 'finds_deadline__lte', 'finds_deadline__gte', ], + relative_session_names=[('file', 'associated_file__pk')], extra_request_keys={ 'common_name': 'common_name__icontains', 'comment': 'comment__icontains', @@ -224,7 +225,7 @@ get_administrativeactop = get_item( 'operation__associated_file__parcels__public_domain'), }, reversed_bool_fields=['index__isnull'], - relative_session_names={'operation': 'operation__pk'}) + relative_session_names=[('operation', 'operation__pk')]) get_administrativeact = get_item( models.AdministrativeAct, diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 50c647372..d55181067 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -578,6 +578,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], reqs = reqs | q and_reqs.append(reqs) if 'submited' not in request_items: + # default search + # an item is selected in the default menu if default_name in request.session and \ request.session[default_name]: value = request.session[default_name] @@ -586,11 +588,11 @@ def get_item(model, func_name, default_name, extra_request_keys=[], request.session[default_name].split('-')[-1]} else: dct = {"pk": request.session[default_name]} - elif not dct: - for name in relative_session_names.keys(): + elif dct == base_request: + # a parent item may be selected in the default menu + for name, key in relative_session_names: if name in request.session and request.session[name]: - k = relative_session_names[name] - dct = {k: request.session[name]} + dct.update({key: request.session[name]}) break if (not dct or data_type == 'csv') \ and func_name in request.session: -- cgit v1.2.3