From a850add6d883d0a0daed8d1c74da5ace6572431e Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 16 Mar 2016 19:48:43 +0100 Subject: Changing context record of a find (refs #3080) --- ishtar_common/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ishtar_common/templates') diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 578b3edcc..4f84e3e62 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -87,7 +87,7 @@ {% endif %}{% endblock %} {% endif %} {% if reminders %}
{% trans "Current items" %} -{% for lbl, value in reminders%} +{% for lbl, value in reminders %}

{{lbl}}{% trans ":"%} {{value}}

{% endfor %}
{%endif%} -- cgit v1.2.3 From 34f93c2502c4048badae52bc9527cc213bba94a0 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 18 May 2016 20:33:35 +0200 Subject: Delete basket --- archaeological_finds/forms.py | 20 ++++++++++++++++++++ archaeological_finds/urls.py | 3 +++ archaeological_finds/views.py | 19 +++++++++++++++---- ishtar_common/templates/ishtar/form_delete.html | 14 ++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 ishtar_common/templates/ishtar/form_delete.html (limited to 'ishtar_common/templates') diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 2b3586979..3c06af375 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -411,6 +411,26 @@ class NewFindBasketForm(forms.ModelForm): self.instance.user = self.user return super(NewFindBasketForm, self).save(commit) + +class DeleteFindBasketForm(forms.Form): + basket = forms.ChoiceField(label=_(u"Basket"), required=True, choices=[]) + + def __init__(self, *args, **kwargs): + self.user = kwargs.pop('user') + super(DeleteFindBasketForm, self).__init__(*args, **kwargs) + self.fields['basket'].choices = [('', '--')] + [ + (b.pk, unicode(b)) + for b in models.FindBasket.objects.filter(user=self.user)] + + def save(self): + try: + models.FindBasket.objects.get(pk=self.cleaned_data['basket'], + user=self.user).delete() + except models.FindBasket.DoesNotExist: + # something strange... TODO: log it + pass + return + """ #################################### # Source management for treatments # diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index bbf9aa976..12c8c0b25 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -58,6 +58,9 @@ urlpatterns = patterns( url(r'^find_basket_creation/$', check_rights(['change_find', 'change_own_find'])( views.NewFindBasketView.as_view()), name='new_findbasket'), + url(r'^find_basket_deletion/$', + check_rights(['change_find', 'change_own_find'])( + views.DeleteFindBasketView.as_view()), name='delete_findbasket'), ) urlpatterns += patterns( diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index e40a3acb9..b079af200 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -21,7 +21,7 @@ from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ -from django.views.generic.edit import CreateView, DeleteView +from django.views.generic.edit import CreateView, FormView from ishtar_common.forms import FinalForm from ishtar_common.forms_common import SourceForm, AuthorFormset, \ @@ -169,7 +169,6 @@ class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): def get_form_kwargs(self): kwargs = super(NewFindBasketView, self).get_form_kwargs() kwargs['user'] = IshtarUser.objects.get(pk=self.request.user.pk) - print(kwargs) return kwargs def get_success_url(self): @@ -180,8 +179,20 @@ class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): return HttpResponseRedirect(self.get_success_url()) -class DeleteFindBasketView(IshtarMixin, LoginRequiredMixin, DeleteView): - pass +class DeleteFindBasketView(IshtarMixin, LoginRequiredMixin, FormView): + template_name = 'ishtar/form_delete.html' + form_class = DeleteFindBasketForm + success_url = '/' + page_name = _(u"Delete basket") + + def get_form_kwargs(self): + kwargs = super(DeleteFindBasketView, self).get_form_kwargs() + kwargs['user'] = IshtarUser.objects.get(pk=self.request.user.pk) + return kwargs + + def form_valid(self, form): + form.save() + return HttpResponseRedirect(self.get_success_url()) """ treatment_creation_wizard = TreatmentWizard.as_view([ diff --git a/ishtar_common/templates/ishtar/form_delete.html b/ishtar_common/templates/ishtar/form_delete.html new file mode 100644 index 000000000..6243e9423 --- /dev/null +++ b/ishtar_common/templates/ishtar/form_delete.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load i18n inline_formset %} +{% block content %} +

{{page_name}}

+
+
{% csrf_token %} + +{{form}} +
+ +
+
+{% endblock %} -- cgit v1.2.3 From 7ff90a0ac951720a3c2d23aca7f2af6ffdf1b7e3 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 19 May 2016 01:38:17 +0200 Subject: Manage basket content --- archaeological_files/ishtar_menu.py | 2 +- archaeological_finds/forms.py | 31 ++++++++- archaeological_finds/ishtar_menu.py | 10 +-- archaeological_finds/models.py | 12 ++++ archaeological_finds/urls.py | 19 ++++++ archaeological_finds/views.py | 82 ++++++++++++++++++++++- ishtar_common/templates/ishtar/basket_list.html | 5 ++ ishtar_common/templates/ishtar/manage_basket.html | 38 +++++++++++ ishtar_common/templates/ishtar/simple_form.html | 11 +++ 9 files changed, 198 insertions(+), 12 deletions(-) create mode 100644 ishtar_common/templates/ishtar/basket_list.html create mode 100644 ishtar_common/templates/ishtar/manage_basket.html create mode 100644 ishtar_common/templates/ishtar/simple_form.html (limited to 'ishtar_common/templates') diff --git a/archaeological_files/ishtar_menu.py b/archaeological_files/ishtar_menu.py index 326fec23b..dfff7d0ab 100644 --- a/archaeological_files/ishtar_menu.py +++ b/archaeological_files/ishtar_menu.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2014 Étienne Loks +# Copyright (C) 2010-2016 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 3c06af375..95af01719 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -24,6 +24,7 @@ Finds forms definitions from django import forms from django.conf import settings from django.core import validators +from django.core.exceptions import PermissionDenied from django.forms.formsets import formset_factory from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -412,16 +413,18 @@ class NewFindBasketForm(forms.ModelForm): return super(NewFindBasketForm, self).save(commit) -class DeleteFindBasketForm(forms.Form): +class SelectFindBasketForm(forms.Form): basket = forms.ChoiceField(label=_(u"Basket"), required=True, choices=[]) def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') - super(DeleteFindBasketForm, self).__init__(*args, **kwargs) + super(SelectFindBasketForm, self).__init__(*args, **kwargs) self.fields['basket'].choices = [('', '--')] + [ (b.pk, unicode(b)) for b in models.FindBasket.objects.filter(user=self.user)] + +class DeleteFindBasketForm(SelectFindBasketForm): def save(self): try: models.FindBasket.objects.get(pk=self.cleaned_data['basket'], @@ -431,6 +434,30 @@ class DeleteFindBasketForm(forms.Form): pass return + +class FindBasketAddItemForm(forms.Form): + basket_id = forms.IntegerField(required=True) + item_id = forms.IntegerField(required=True) + + def save(self, user): + try: + basket = models.FindBasket.objects.get( + pk=self.cleaned_data['basket_id'], user=user.ishtaruser) + item = models.Find.objects.get( + pk=self.cleaned_data['item_id']) + except models.FindBasket.DoesNotExist or\ + models.Find.DoesNotExist: + # something strange... TODO: log it + raise PermissionDenied + # check rights + if not user.is_superuser and \ + not user.ishtaruser.has_right('change_find') and \ + not (user.ishtaruser.has_right('change_own_find') + and item.is_own(user)): + raise PermissionDenied + basket.items.add(item) + return basket + """ #################################### # Source management for treatments # diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index 9eaf601f2..d7a67091a 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2012-2015 Étienne Loks +# Copyright (C) 2012-2016 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -64,13 +64,7 @@ MENU_SECTIONS = [ access_controls=['change_find', 'change_own_find']), MenuItem('find_basket_modification_add', - _(u"Add items"), - model=models.FindBasket, - access_controls=[ - 'change_find', - 'change_own_find']), - MenuItem('find_basket_modification_del', - _(u"Delete items"), + _(u"Manage items"), model=models.FindBasket, access_controls=[ 'change_find', diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index bd446235b..068debdb0 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -372,6 +372,18 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): return u" - ".join([base_find.name for base_find in self.base_finds.all()]) + @property + def full_label(self): + lbl = u" - ".join([ + getattr(self, attr) + for attr in ('label', 'administrative_index') + if getattr(self, attr)]) + base = u" - ".join([base_find.complete_id() + for base_find in self.base_finds.all()]) + if base: + lbl += ' ({})'.format(base) + return lbl + def get_first_base_find(self): q = self.base_finds if not q.count(): diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 12c8c0b25..4629a38a5 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -58,6 +58,25 @@ urlpatterns = patterns( url(r'^find_basket_creation/$', check_rights(['change_find', 'change_own_find'])( views.NewFindBasketView.as_view()), name='new_findbasket'), + url(r'^find_basket_creation/$', + check_rights(['change_find', 'change_own_find'])( + views.NewFindBasketView.as_view()), name='new_findbasket'), + url(r'^find_basket_modification_add/$', + check_rights(['change_find', 'change_own_find'])( + views.SelectBasketForAdd.as_view()), + name='select_findbasketforadd'), + url(r'^find_basket_modification_add/(?P[0-9]+)?/$', + check_rights(['change_find', 'change_own_find'])( + views.SelectItemsInBasket.as_view()), + name='select_itemsinbasket'), + url(r'^find_basket_modification_add_item/$', + check_rights(['change_find', 'change_own_find'])( + views.FindBasketAddItemView.as_view()), + name='add_iteminbasket'), + url(r'^find_basket_list/(?P[0-9]+)?/$', + check_rights(['change_find', 'change_own_find'])( + views.FindBasketListView.as_view()), + name='list_iteminbasket'), url(r'^find_basket_deletion/$', check_rights(['change_find', 'change_own_find'])( views.DeleteFindBasketView.as_view()), name='delete_findbasket'), diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index b079af200..a43ebaa12 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -17,10 +17,12 @@ # See the file COPYING for details. +from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ +from django.views.generic import TemplateView from django.views.generic.edit import CreateView, FormView from ishtar_common.forms import FinalForm @@ -172,13 +174,91 @@ class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): return kwargs def get_success_url(self): - return reverse('new_findbasket') + return reverse('select_itemsinbasket', + kwargs={'pk': self.object.pk}) def form_valid(self, form): self.object = form.save() return HttpResponseRedirect(self.get_success_url()) +class SelectBasketForAdd(IshtarMixin, LoginRequiredMixin, FormView): + template_name = 'ishtar/form.html' + form_class = SelectFindBasketForm + page_name = _(u"Add items to basket") + + def get_form_kwargs(self): + kwargs = super(SelectBasketForAdd, self).get_form_kwargs() + kwargs['user'] = IshtarUser.objects.get(pk=self.request.user.pk) + if 'pk' in self.kwargs: + kwargs['initial'].update({'basket': self.kwargs['pk']}) + return kwargs + + def get_success_url(self, basket): + return reverse('select_itemsinbasket', + kwargs={'pk': basket}) + + def form_valid(self, form): + return HttpResponseRedirect(self.get_success_url( + form.cleaned_data['basket'])) + + +class SelectItemsInBasket(IshtarMixin, LoginRequiredMixin, TemplateView): + template_name = 'ishtar/manage_basket.html' + page_name = _(u"Manage basket") + + def get_context_data(self, *args, **kwargs): + context = super(SelectItemsInBasket, self).get_context_data( + *args, **kwargs) + self.user = IshtarUser.objects.get(pk=self.request.user.pk) + try: + self.basket = models.FindBasket.objects.get( + pk=self.kwargs['pk'], user=self.user) + except models.FindBasket.DoesNotExist: + raise PermissionDenied + context['basket'] = self.basket + context['form'] = FindFormSelection() + context['add_url'] = reverse('add_iteminbasket') + context['list_url'] = reverse('list_iteminbasket', + kwargs={'pk': self.basket.pk}) + return context + + def form_valid(self, form): + return HttpResponseRedirect(self.get_success_url()) + + +class FindBasketAddItemView(IshtarMixin, LoginRequiredMixin, FormView): + template_name = 'ishtar/simple_form.html' + form_class = FindBasketAddItemForm + + def get_success_url(self, basket): + return reverse('list_iteminbasket', kwargs={'pk': basket.pk}) + + def form_valid(self, form): + user = IshtarUser.objects.get(pk=self.request.user.pk) + # rights are checked on the form + basket = form.save(user) + return HttpResponseRedirect(self.get_success_url(basket)) + + +class FindBasketListView(IshtarMixin, LoginRequiredMixin, TemplateView): + template_name = 'ishtar/basket_list.html' + + def get_context_data(self, *args, **kwargs): + context = super(FindBasketListView, self).get_context_data( + *args, **kwargs) + self.user = IshtarUser.objects.get(pk=self.request.user.pk) + try: + self.basket = models.FindBasket.objects.get( + pk=self.kwargs['pk'], user=self.user) + except models.FindBasket.DoesNotExist: + raise PermissionDenied + context['basket'] = self.basket + context['item_url'] = '/'.join( + reverse(models.Find.SHOW_URL, args=[1]).split('/')[:-2]) + return context + + class DeleteFindBasketView(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/form_delete.html' form_class = DeleteFindBasketForm diff --git a/ishtar_common/templates/ishtar/basket_list.html b/ishtar_common/templates/ishtar/basket_list.html new file mode 100644 index 000000000..5a7af2bc6 --- /dev/null +++ b/ishtar_common/templates/ishtar/basket_list.html @@ -0,0 +1,5 @@ +{% load i18n %} + diff --git a/ishtar_common/templates/ishtar/manage_basket.html b/ishtar_common/templates/ishtar/manage_basket.html new file mode 100644 index 000000000..44c3a2536 --- /dev/null +++ b/ishtar_common/templates/ishtar/manage_basket.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} +{% load i18n inline_formset %} +{% block content %} +

{{page_name}}{% trans ":"%} {{basket}}

+
{% csrf_token %} +
+{{form}} + +

{% trans "Basket content" %}

+
+
+
+
+ +{% endblock %} diff --git a/ishtar_common/templates/ishtar/simple_form.html b/ishtar_common/templates/ishtar/simple_form.html new file mode 100644 index 000000000..e3a464459 --- /dev/null +++ b/ishtar_common/templates/ishtar/simple_form.html @@ -0,0 +1,11 @@ +{% load i18n %} + + +
+
{% csrf_token %} +{{form}} + +
+
+ + -- cgit v1.2.3 From 5a1a52a3e1996793eb22955a82915966d7abb279 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 22 May 2016 16:08:55 +0200 Subject: Basket: manage deletion --- archaeological_finds/urls.py | 7 ++++- archaeological_finds/views.py | 38 ++++++++++++++++++++++--- ishtar_common/static/js/ishtar.js | 12 +++++++- ishtar_common/templates/ishtar/basket_list.html | 13 ++++++--- 4 files changed, 60 insertions(+), 10 deletions(-) (limited to 'ishtar_common/templates') diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 4629a38a5..deaaaff18 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -63,7 +63,7 @@ urlpatterns = patterns( views.NewFindBasketView.as_view()), name='new_findbasket'), url(r'^find_basket_modification_add/$', check_rights(['change_find', 'change_own_find'])( - views.SelectBasketForAdd.as_view()), + views.SelectBasketForManagement.as_view()), name='select_findbasketforadd'), url(r'^find_basket_modification_add/(?P[0-9]+)?/$', check_rights(['change_find', 'change_own_find'])( @@ -73,6 +73,11 @@ urlpatterns = patterns( check_rights(['change_find', 'change_own_find'])( views.FindBasketAddItemView.as_view()), name='add_iteminbasket'), + url(r'^find_basket_modification_delete_item/(?P[0-9]+)?' + r'/(?P[0-9]+)?/$', + check_rights(['change_find', 'change_own_find'])( + views.FindBasketDeleteItemView.as_view()), + name='delete_iteminbasket'), url(r'^find_basket_list/(?P[0-9]+)?/$', check_rights(['change_find', 'change_own_find'])( views.FindBasketListView.as_view()), diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index a43ebaa12..851245201 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -182,13 +182,13 @@ class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): return HttpResponseRedirect(self.get_success_url()) -class SelectBasketForAdd(IshtarMixin, LoginRequiredMixin, FormView): +class SelectBasketForManagement(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/form.html' form_class = SelectFindBasketForm - page_name = _(u"Add items to basket") + page_name = _(u"Manage items in basket") def get_form_kwargs(self): - kwargs = super(SelectBasketForAdd, self).get_form_kwargs() + kwargs = super(SelectBasketForManagement, self).get_form_kwargs() kwargs['user'] = IshtarUser.objects.get(pk=self.request.user.pk) if 'pk' in self.kwargs: kwargs['initial'].update({'basket': self.kwargs['pk']}) @@ -255,10 +255,40 @@ class FindBasketListView(IshtarMixin, LoginRequiredMixin, TemplateView): raise PermissionDenied context['basket'] = self.basket context['item_url'] = '/'.join( - reverse(models.Find.SHOW_URL, args=[1]).split('/')[:-2]) + reverse(models.Find.SHOW_URL, args=[1]).split('/')[:-1]) + context['delete_url'] = '/'.join( + reverse('delete_iteminbasket', args=[1, 1]).split('/')[:-3]) return context +class FindBasketDeleteItemView(IshtarMixin, LoginRequiredMixin, TemplateView): + template_name = 'ishtar/simple_form.html' + + def get_success_url(self, basket): + return reverse('list_iteminbasket', kwargs={'pk': basket.pk}) + + def get(self, *args, **kwargs): + user = self.request.user + ishtaruser = IshtarUser.objects.get(pk=self.request.user.pk) + try: + find = models.Find.objects.get( + pk=self.kwargs['find_pk']) + except models.Find.DoesNotExist: + raise PermissionDenied + try: + basket = models.FindBasket.objects.get( + pk=self.kwargs['basket'], user=ishtaruser) + except models.FindBasket.DoesNotExist: + raise PermissionDenied + if not user.is_superuser and \ + not ishtaruser.has_right('change_find') and \ + not (ishtaruser.has_right('change_own_find') + and find.is_own(user)): + raise PermissionDenied + basket.items.remove(find) + return HttpResponseRedirect(self.get_success_url(basket)) + + class DeleteFindBasketView(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/form_delete.html' form_class = DeleteFindBasketForm diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 9af5cf2b0..f469fc546 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -23,6 +23,15 @@ beforeSend: function(xhr, settings) { } }}); +function manage_async_link(event){ + event.preventDefault(); + var url = $(this).attr('href'); + var target = $(this).attr('data-target'); + $.get(url, function(data) { + $(target).html(data); + }); +} + /* default function to prevent undefined */ function get_next_table_id(){} function get_previous_table_id(){} @@ -63,7 +72,8 @@ $(document).ready(function(){ } $('#current_items select').change(function(){ $(this).attr('class', $(this).children("option:selected").attr('class')); - }) + }); + $("a.async-link").click(manage_async_link); }); $(document).on("click", '#to_bottom_arrow', function(){ diff --git a/ishtar_common/templates/ishtar/basket_list.html b/ishtar_common/templates/ishtar/basket_list.html index 5a7af2bc6..a0a0e5d73 100644 --- a/ishtar_common/templates/ishtar/basket_list.html +++ b/ishtar_common/templates/ishtar/basket_list.html @@ -1,5 +1,10 @@ {% load i18n %} - + +{% for item in basket.items.all %} + + + {% endfor %} +
{% trans 'Details' %}{{item.full_label}}{% trans "remove" %}
+ -- cgit v1.2.3 From f937d282b0ac0864da5651176a3c95418d1e0575 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 22 May 2016 17:02:11 +0200 Subject: Basket management: select multiple - select all --- archaeological_finds/forms.py | 14 ++++++++++++ archaeological_finds/views.py | 2 +- ishtar_common/templates/blocks/JQueryJqGrid.html | 1 + ishtar_common/templates/ishtar/manage_basket.html | 26 +++++++++++++---------- ishtar_common/widgets.py | 5 ++++- 5 files changed, 35 insertions(+), 13 deletions(-) (limited to 'ishtar_common/templates') diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 95af01719..ca2946a21 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -251,6 +251,20 @@ class FindFormSelection(forms.Form): validators=[valid_id(models.Find)]) +class MultipleFindFormSelection(forms.Form): + form_label = _("Find search") + associated_models = {'pk': models.Find} + currents = {'pk': models.Find} + pk = forms.IntegerField( + label="", required=False, + widget=widgets.JQueryJqGrid( + reverse_lazy('get-find'), + FindSelect, models.Find, + multiple_select=True, + source_full=reverse_lazy('get-find-full')), + validators=[valid_id(models.Find)]) + + class BaseTreatmentForm(forms.Form): form_label = _(u"Base treatment") associated_models = {'treatment_type': models.TreatmentType, diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 851245201..871a5b90d 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -217,7 +217,7 @@ class SelectItemsInBasket(IshtarMixin, LoginRequiredMixin, TemplateView): except models.FindBasket.DoesNotExist: raise PermissionDenied context['basket'] = self.basket - context['form'] = FindFormSelection() + context['form'] = MultipleFindFormSelection() context['add_url'] = reverse('add_iteminbasket') context['list_url'] = reverse('list_iteminbasket', kwargs={'pk': self.basket.pk}) diff --git a/ishtar_common/templates/blocks/JQueryJqGrid.html b/ishtar_common/templates/blocks/JQueryJqGrid.html index 063a3c1da..c6a15243a 100644 --- a/ishtar_common/templates/blocks/JQueryJqGrid.html +++ b/ishtar_common/templates/blocks/JQueryJqGrid.html @@ -90,6 +90,7 @@ jQuery(document).ready(function(){ width: null, shrinkToFit: false, rowNum:20, + {% if multiple_select %}multiselect: true,{% endif %} jsonReader : {repeatitems: false}, loadError: function (jqXHR, textStatus, errorThrown) { alert("{% trans "An error as occured during search. Check your query fields." %}"); diff --git a/ishtar_common/templates/ishtar/manage_basket.html b/ishtar_common/templates/ishtar/manage_basket.html index 44c3a2536..6332b326e 100644 --- a/ishtar_common/templates/ishtar/manage_basket.html +++ b/ishtar_common/templates/ishtar/manage_basket.html @@ -4,6 +4,7 @@

{{page_name}}{% trans ":"%} {{basket}}

{% csrf_token %}
+

{% trans 'Checking "Select all" only select the current page.' %}

{{form}}

{% trans "Basket content" %}

@@ -18,17 +19,20 @@ function load_list(data){ } $('#add_to').click(function(){ - selected_item = jQuery("#grid_pk").getGridParam('selrow'); - if(!selected_item) return false; - $.ajax({ - type: "POST", - url: '{{add_url}}', - data: { - basket_id: {{basket.pk}}, - item_id: selected_item - }, - success: load_list - }); + var selected_items = jQuery("#grid_pk").getGridParam('selarrrow'); + if(!selected_items) return false; + for (i = 0, n = selected_items.length; i < n; i++) { + var selected_item = selected_items[i]; + $.ajax({ + type: "POST", + url: '{{add_url}}', + data: { + basket_id: {{basket.pk}}, + item_id: selected_item + }, + success: load_list + }); + } return false; }); jQuery(document).ready(function(){ diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index b8b104a61..6d9600d0c 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -513,13 +513,15 @@ class JQueryJqGrid(forms.RadioSelect): def __init__(self, source, form, associated_model, attrs={}, table_cols='TABLE_COLS', multiple=False, multiple_cols=[2], - new=False, new_message="", source_full=None): + new=False, new_message="", source_full=None, + multiple_select=False): self.source = source self.form = form self.attrs = attrs self.associated_model = associated_model self.table_cols = table_cols self.multiple = multiple + self.multiple_select = multiple_select self.multiple_cols = multiple_cols self.new, self.new_message = new, new_message self.source_full = source_full @@ -604,6 +606,7 @@ class JQueryJqGrid(forms.RadioSelect): 'remove': unicode(_(u"Remove")), 'sname': name.replace('-', ''), 'multiple': self.multiple, + 'multiple_select': self.multiple_select, 'multi_cols': ",".join((u'"%d"' % col for col in self.multiple_cols))}) t = loader.get_template('blocks/JQueryJqGrid.html') -- cgit v1.2.3 From 56959b906bf2e628a04a30be32a946a64d453c06 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 22 May 2016 22:22:32 +0200 Subject: Find: sheet for basket - manage default basket selection --- archaeological_finds/models.py | 7 ++++++- .../templates/ishtar/sheet_findbasket.html | 16 ++++++++++++++++ .../templates/ishtar/sheet_findbasket_pdf.html | 18 ++++++++++++++++++ .../templates/ishtar/sheet_findbasket_window.html | 3 +++ archaeological_finds/urls.py | 5 ++--- archaeological_finds/views.py | 3 +++ ishtar_common/context_processors.py | 7 +++++-- ishtar_common/models.py | 10 ++++++++++ ishtar_common/static/media/style.css | 6 ++++++ ishtar_common/templates/base.html | 2 +- .../ishtar/blocks/window_tables/dynamic_documents.html | 1 + ishtar_common/templatetags/window_tables.py | 15 +++++++++++++-- ishtar_common/views.py | 7 ++++++- 13 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 archaeological_finds/templates/ishtar/sheet_findbasket.html create mode 100644 archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html create mode 100644 archaeological_finds/templates/ishtar/sheet_findbasket_window.html (limited to 'ishtar_common/templates') diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index af3009351..43c18828c 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -384,6 +384,10 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): lbl += u' ({})'.format(base) return lbl + @classmethod + def get_owns(cls, user): + return FindBasket.objects.filter(user=user) + def get_first_base_find(self): q = self.base_finds if not q.count(): @@ -541,7 +545,8 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): class FindBasket(Basket): - items = models.ManyToManyField(Find, blank=True, null=True) + items = models.ManyToManyField(Find, blank=True, null=True, + related_name='basket') class FindSource(Source): diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket.html b/archaeological_finds/templates/ishtar/sheet_findbasket.html new file mode 100644 index 000000000..00b52ab7b --- /dev/null +++ b/archaeological_finds/templates/ishtar/sheet_findbasket.html @@ -0,0 +1,16 @@ +{% extends "ishtar/sheet.html" %} +{% load i18n window_tables from_dict %} + +{% block head_sheet %} +{{block.super}} +

{% trans "Find"%}

+{% endblock %} + +{% block content %} + + + + +{% dynamic_table_document_large finds 'finds_for_ope' 'basket' item.pk 'TABLE_COLS_FOR_OPE' output %} + +{% endblock %} diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html b/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html new file mode 100644 index 000000000..37eecf81b --- /dev/null +++ b/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html @@ -0,0 +1,18 @@ +{% extends "ishtar/sheet_findbasket.html" %} +{% block header %} + +{% endblock %} +{% block main_head %} +{{ block.super }} +
+Ishtar – {{APP_NAME}} – {{item}} +
+{% endblock %} +{%block head_sheet%}{%endblock%} +{%block main_foot%} +
+– – +
+ + +{%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket_window.html b/archaeological_finds/templates/ishtar/sheet_findbasket_window.html new file mode 100644 index 000000000..5bc46d5c7 --- /dev/null +++ b/archaeological_finds/templates/ishtar/sheet_findbasket_window.html @@ -0,0 +1,3 @@ +{% extends "ishtar/sheet_findbasket.html" %} +{% block main_head %}{%endblock%} +{% block main_foot %}{%endblock%} diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index deaaaff18..27a2bdc76 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -58,9 +58,6 @@ urlpatterns = patterns( url(r'^find_basket_creation/$', check_rights(['change_find', 'change_own_find'])( views.NewFindBasketView.as_view()), name='new_findbasket'), - url(r'^find_basket_creation/$', - check_rights(['change_find', 'change_own_find'])( - views.NewFindBasketView.as_view()), name='new_findbasket'), url(r'^find_basket_modification_add/$', check_rights(['change_find', 'change_own_find'])( views.SelectBasketForManagement.as_view()), @@ -113,6 +110,8 @@ urlpatterns += patterns( 'get_findsource', name='get-findsource'), url(r'show-findsource(?:/(?P.+))?/(?P.+)?$', 'show_findsource', name=models.FindSource.SHOW_URL), + url(r'show-find/basket-(?P.+)/(?P.+)?$', 'show_findbasket', + name='show-findbasket'), url(r'show-find(?:/(?P.+))?/(?P.+)?$', 'show_find', name=models.Find.SHOW_URL), url(r'show-historized-find/(?P.+)?/(?P.+)?$', diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 871a5b90d..77d3522ca 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -62,6 +62,7 @@ find_extra_keys = { 'base_finds__find__description': 'base_finds__find__description__icontains', 'base_finds__batch': 'base_finds__batch', + 'basket': 'basket', 'image': 'image__isnull'} get_find = get_item( @@ -95,6 +96,8 @@ get_findsource = get_item( show_find = show_item(models.Find, 'find') revert_find = revert_item(models.Find) +show_findbasket = show_item(models.FindBasket, 'findbasket') + find_creation_wizard = FindWizard.as_view([ ('selecrecord-find_creation', RecordFormSelection), ('find-find_creation', FindForm), diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py index 03ba9bc36..76f58bf8e 100644 --- a/ishtar_common/context_processors.py +++ b/ishtar_common/context_processors.py @@ -77,10 +77,13 @@ def get_base_context(request): current = model_name in request.session and request.session[model_name] items = [] for item in model.get_owns(request.user): - selected = unicode(item.pk) == current + pk = unicode(item.pk) + if item.IS_BASKET: + pk = "basket-" + pk + selected = pk == current if selected: cls = item.get_short_menu_class() - items.append((item.pk, shortify(unicode(item), 60), + items.append((pk, shortify(unicode(item), 60), selected, item.get_short_menu_class())) if items: dct['current_menu'].append((lbl, model_name, cls, items)) diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 3162a4843..33ae05369 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -480,6 +480,7 @@ class Basket(models.Model): Abstract class for a basket Subclass must be defined with an "items" ManyToManyField """ + IS_BASKET = True label = models.CharField(_(u"Label"), max_length=1000) comment = models.TextField(_(u"Comment"), blank=True, null=True) user = models.ForeignKey('IshtarUser', blank=True, null=True) @@ -492,6 +493,14 @@ class Basket(models.Model): def __unicode__(self): return self.label + def get_short_menu_class(self): + return 'basket' + + @property + def associated_filename(self): + return "{}-{}".format(datetime.date.today().strftime( + "%Y-%m-%d"), slugify(self.label)) + class ItemKey(models.Model): key = models.CharField(_(u"Key"), max_length=100) @@ -569,6 +578,7 @@ class HistoryError(Exception): class BaseHistorizedItem(Imported): + IS_BASKET = False history_modifier = models.ForeignKey( User, related_name='+', on_delete=models.SET_NULL, verbose_name=_(u"Last editor"), blank=True, null=True) diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css index 1590c1738..1d47bcbd9 100644 --- a/ishtar_common/static/media/style.css +++ b/ishtar_common/static/media/style.css @@ -45,6 +45,12 @@ a.add-button, color:#000; } +#context_menu .basket{ + color:#000; + font-weight: bold; + font-style: italic; +} + /* borders */ a.add-button, a.remove, #progress-content, diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 4f84e3e62..1bab3d647 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -74,7 +74,7 @@ {% with 'show-'|add:model_name as model_url%} {% trans "Details" %} diff --git a/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html b/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html index 7239b64fc..8850bd34a 100644 --- a/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html +++ b/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html @@ -42,6 +42,7 @@ setTimeout( alert("{% trans "An error as occured during search. Check your query fields." %}"); } }); + {% if large %}jQuery("#grid_{{name}}").jqGrid('setGridHeight', 400);{% endif %} }, 200); diff --git a/ishtar_common/templatetags/window_tables.py b/ishtar_common/templatetags/window_tables.py index cdd681b52..8be4e5559 100644 --- a/ishtar_common/templatetags/window_tables.py +++ b/ishtar_common/templatetags/window_tables.py @@ -44,8 +44,9 @@ ASSOCIATED_MODELS['finds_docs'] = (FindSource, 'get-findsource', '') @register.simple_tag(takes_context=True) -def dynamic_table_document(context, caption, associated_model, key, value, - table_cols='TABLE_COLS', output='html'): +def dynamic_table_document( + context, caption, associated_model, key, value, + table_cols='TABLE_COLS', output='html', large=False): if not table_cols: table_cols = 'TABLE_COLS' model, url, url_full = ASSOCIATED_MODELS[associated_model] @@ -68,6 +69,7 @@ def dynamic_table_document(context, caption, associated_model, key, value, 'no_result': unicode(_("No results")), 'loading': unicode(_("Loading...")), 'encoding': settings.ENCODING or 'utf-8', + 'large': large }) return t.render(context) else: @@ -103,3 +105,12 @@ def dynamic_table_document(context, caption, associated_model, key, value, 'data': data }) return t.render(context) + + +@register.simple_tag(takes_context=True) +def dynamic_table_document_large( + context, caption, associated_model, key, + value, table_cols='TABLE_COLS', output='html'): + return dynamic_table_document( + context, caption, associated_model, key, + value, table_cols, output, large=True) diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 752cbcc74..59cfe6321 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -417,7 +417,12 @@ def get_item(model, func_name, default_name, extra_request_keys=[], if 'submited' not in request_items: if default_name in request.session and \ request.session[default_name]: - dct = {"pk": request.session[default_name]} + value = request.session[default_name] + if 'basket-' in value: + dct = {"basket__pk": + request.session[default_name].split('-')[-1]} + else: + dct = {"pk": request.session[default_name]} elif not dct: for name in relative_session_names.keys(): if name in request.session and request.session[name]: -- cgit v1.2.3