summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2013-09-03 01:26:53 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2013-09-03 01:38:30 +0200
commitf7abfdbcc4066121d79bd09a389535a19359edc1 (patch)
treeb3547fddea0b516f4f329708e4a9f51995a34157
parent68c2fdd71ac6dc7b90a08790acef6b7d1722605a (diff)
downloadIshtar-f7abfdbcc4066121d79bd09a389535a19359edc1.tar.bz2
Ishtar-f7abfdbcc4066121d79bd09a389535a19359edc1.zip
Add a widget to do free input parcel additions (refs #809)
-rw-r--r--archaeological_operations/forms.py88
-rw-r--r--archaeological_operations/widgets.py9
-rw-r--r--archaeological_operations/wizards.py10
-rw-r--r--ishtar_common/templates/ishtar/wizard/parcels_wizard.html1
4 files changed, 97 insertions, 11 deletions
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index 1fc081ea4..2071dd00f 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -27,16 +27,19 @@ from django.conf import settings
from django.core import validators
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Max
-from django.forms.formsets import DELETION_FIELD_NAME
+from django.forms.formsets import DELETION_FIELD_NAME, TOTAL_FORM_COUNT
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
+from django.utils.safestring import mark_safe
from ishtar_common.models import valid_id, PersonType, Person, Town
from archaeological_files.models import File
import models
-from widgets import ParcelWidget
+
+from widgets import ParcelWidget, SelectParcelWidget
from ishtar_common import widgets
+
from ishtar_common.forms import BaseFormSet, FinalForm, FormSet, \
ClosingDateFormSelection, formset_factory, get_now, reverse_lazy, \
get_form_selection, TableSelect
@@ -44,6 +47,8 @@ from ishtar_common.forms_common import TownForm, TownFormSet, TownFormset, \
AuthorFormset, SourceForm, SourceSelect, \
SourceDeletionForm, get_town_field
+from archaeological_operations.utils import parse_parcels
+
class ParcelField(forms.MultiValueField):
def __init__(self, *args, **kwargs):
if 'widget' not in kwargs:
@@ -96,15 +101,84 @@ class ParcelForm(forms.Form):
u"fields are required."))
return self.cleaned_data
+class ParcelSelectionForm(forms.Form):
+ _parcel_selection = forms.CharField(label=_(u"Full text input"),
+ widget=SelectParcelWidget(attrs={'class':'parcel-select'}),
+ max_length=100, help_text=_(u"example: \"2013: XD:1 to "\
+ u"13,24,33 to 39, YD:24\" or \"AB:24,AC:42\""),
+ required=False)
+
class ParcelFormSet(FormSet):
+ SELECTION_FORM = ParcelSelectionForm
+
+ def __init__(self, *args, **kwargs):
+ super(FormSet, self).__init__(*args, **kwargs)
+ if self.forms[0].__class__.__name__ == 'ParcelForm':
+ self.selection_form = ParcelSelectionForm()
+
+ def as_table(self):
+ # add dynamic widget
+ render = self.selection_form.as_table()
+ render += super(FormSet, self).as_table()
+ return mark_safe(render)
+
+ def as_p(self):
+ # add dynamic widget
+ render = self.selection_form.as_p()
+ render += super(FormSet, self).as_p()
+ return mark_safe(render)
+
+ def as_ul(self):
+ # add dynamic widget
+ render = self.selection_form.as_ul()
+ render += super(FormSet, self).as_ul()
+ return mark_safe(render)
+
def add_fields(self, form, index):
super(FormSet, self).add_fields(form, index)
def clean(self):
- """Checks that no parcels are duplicated."""
- return self.check_duplicate(('town', 'section',
- 'parcel_number', 'year'),
- _(u"There are identical parcels."))
+ # manage parcel selection
+ last_town, parcels = None, []
+ if hasattr(self, 'cleaned_data') and self.cleaned_data:
+ for parcel in reversed(self.cleaned_data):
+ if parcel.get('town'):
+ last_town = parcel.get('town')
+ break
+ if not last_town:
+ towns = self.forms[0].fields['town'].choices
+ if towns:
+ towns.pop(0) # remove first empty
+ if towns:
+ last_town = towns[0][0]
+ if self.data.get('_parcel_selection'):
+ parcels = parse_parcels(self.data['_parcel_selection'])
+ if last_town:
+ for idx, parcel in enumerate(parcels):
+ parcel['town'] = last_town
+ parcel['DELETE'] = False
+ parcels[idx] = parcel
+ c_max = self.total_form_count()
+ # pop the last extra form
+ extra_form = self.forms.pop()
+ for idx, parcel in enumerate(parcels):
+ form = self._construct_form(idx + c_max)
+ for k in parcel:
+ self.data[form.prefix+'-'+k] = parcel[k]
+ # reconstruct with correct binded data
+ form = self._construct_form(idx + c_max)
+ form.cleaned_data = parcel
+ self.forms.append(form)
+ self._errors.append(None)
+ self.forms.append(extra_form)
+ self.data[self.prefix+'-'+TOTAL_FORM_COUNT] = c_max + len(parcels)
+ self.management_form.data = self.data
+ self.management_form.is_valid()
+ # Checks that no parcels are duplicated.
+ self.check_duplicate(('town', 'section', 'parcel_number',
+ 'year'), _(u"There are identical parcels."))
+ if hasattr(self, 'cleaned_data') and self.cleaned_data:
+ return self.cleaned_data
ParcelFormSet = formset_factory(ParcelForm, can_delete=True,
formset=ParcelFormSet)
@@ -171,7 +245,7 @@ class OperationFormSelection(forms.Form):
return cleaned_data
class OperationCodeInput(forms.TextInput):
- """Manage auto complete whene changing year in form"""
+ """Manage auto complete when changing year in form"""
def render(self, *args, **kwargs):
name, value = args
base_name = '-'.join(name.split('-')[:-1])
diff --git a/archaeological_operations/widgets.py b/archaeological_operations/widgets.py
index 0e84b2047..6c4ebe79a 100644
--- a/archaeological_operations/widgets.py
+++ b/archaeological_operations/widgets.py
@@ -19,6 +19,8 @@
from django import forms
from django.forms import widgets
+from django.utils.safestring import mark_safe
+from django.utils.translation import ugettext_lazy as _
class ParcelWidget(widgets.MultiWidget):
def __init__(self, attrs=None):
@@ -41,3 +43,10 @@ class ParcelWidget(widgets.MultiWidget):
def format_output(self, rendered_widgets):
return u' / '.join(rendered_widgets)
+
+class SelectParcelWidget(widgets.TextInput):
+ def render(self, *args, **kwargs):
+ render = super(SelectParcelWidget, self).render(*args, **kwargs)
+ render += u" <button name='formset_add' value='add'>%s</button>" \
+ % _(u"Add")
+ return mark_safe(render)
diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py
index d24b380dd..91f4be3d4 100644
--- a/archaeological_operations/wizards.py
+++ b/archaeological_operations/wizards.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2012-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -138,6 +138,8 @@ class OperationWizard(Wizard):
def get_form_initial(self, step, data=None):
initial = super(OperationWizard, self).get_form_initial(step)
+ return initial
+ '''
self.form_initialized = False
if not step.startswith(self.parcel_step_key):
return initial
@@ -147,7 +149,7 @@ class OperationWizard(Wizard):
default.pop('parcel_number')
initial.append(default)
# necessary to get the appropriate form number
- self.form_initialized = True
+ #self.form_initialized = True
elif data:
numbers, keys = set(), set()
for k in data:
@@ -160,8 +162,8 @@ class OperationWizard(Wizard):
if numbers and max(numbers) - 1 > 0:
initial = [dict([(k, data[step+'-'+unicode(max(numbers)-1)+'-'+k])
for k in keys if k != 'parcel_number'])]
- self.form_initialized = True
- return initial
+ #self.form_initialized = True
+ return initial'''
class OperationModificationWizard(OperationWizard):
modification = True
diff --git a/ishtar_common/templates/ishtar/wizard/parcels_wizard.html b/ishtar_common/templates/ishtar/wizard/parcels_wizard.html
index 94e9820ab..5aea689dd 100644
--- a/ishtar_common/templates/ishtar/wizard/parcels_wizard.html
+++ b/ishtar_common/templates/ishtar/wizard/parcels_wizard.html
@@ -14,6 +14,7 @@
<table class='formset'>
<tr class='error'><th colspan='2'>{{wizard.form.non_form_errors}}</th></tr>
</table>{%endif%}
+{{wizard.form.selection_form}}
<table class='inline-table'>
<tr>{% for field in wizard.form.forms.0 %}<th>{{ field.label_tag }}</th>{% endfor %}</tr>
{% inline_formset 'Parcels' wizard.form.forms False %}