diff options
| author | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-04-04 14:58:05 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-04-04 17:27:54 +0200 | 
| commit | 8e19be1b27cf14cf0f76d7c4bcd81e520ac95407 (patch) | |
| tree | 388ccdce5f40fe3bda8c457daeb397805925526d | |
| parent | 3f6567507978281761005dc12951511e0c81a9ae (diff) | |
| download | Ishtar-8e19be1b27cf14cf0f76d7c4bcd81e520ac95407.tar.bz2 Ishtar-8e19be1b27cf14cf0f76d7c4bcd81e520ac95407.zip | |
Forms (operations, context records, files): add search by parcel (refs #575)
| -rw-r--r-- | archaeological_context_records/forms.py | 16 | ||||
| -rw-r--r-- | archaeological_context_records/views.py | 7 | ||||
| -rw-r--r-- | archaeological_files/forms.py | 17 | ||||
| -rw-r--r-- | archaeological_files/views.py | 8 | ||||
| -rw-r--r-- | archaeological_finds/forms.py | 4 | ||||
| -rw-r--r-- | archaeological_operations/forms.py | 24 | ||||
| -rw-r--r-- | archaeological_operations/views.py | 14 | ||||
| -rw-r--r-- | archaeological_operations/widgets.py | 43 | ||||
| -rw-r--r-- | archaeological_warehouse/forms.py | 5 | ||||
| -rw-r--r-- | ishtar_common/forms.py | 6 | ||||
| -rw-r--r-- | ishtar_common/forms_common.py | 4 | ||||
| -rw-r--r-- | ishtar_common/static/media/style.css | 3 | ||||
| -rw-r--r-- | ishtar_common/views.py | 2 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 6 | 
14 files changed, 132 insertions, 27 deletions
| diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py index 41e4a1e20..fce5193d6 100644 --- a/archaeological_context_records/forms.py +++ b/archaeological_context_records/forms.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2012  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-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 @@ -36,16 +36,17 @@ import models  from ishtar_common import widgets  from ishtar_common.forms import FinalForm, FinalForm, FormSet, \ -                  formset_factory, get_now, reverse_lazy, get_form_selection +      formset_factory, get_now, reverse_lazy, get_form_selection, TableSelect  from ishtar_common.forms_common import get_town_field, SourceForm, \                                         SourceSelect, AuthorFormset -from archaeological_operations.forms import OperationSelect +from archaeological_operations.forms import OperationSelect, ParcelField -class RecordSelect(forms.Form): +class RecordSelect(TableSelect):      parcel__town = get_town_field()      operation__year = forms.IntegerField(label=_(u"Year"))      datings__period = forms.ChoiceField(label=_(u"Period"), choices=[])      unit = forms.ChoiceField(label=_(u"Unit type"), choices=[]) +    parcel = ParcelField(label=_("Parcel (section/number)"))      def __init__(self, *args, **kwargs):          super(RecordSelect, self).__init__(*args, **kwargs)          self.fields['datings__period'].choices = Period.get_types() @@ -53,6 +54,13 @@ class RecordSelect(forms.Form):          self.fields['unit'].choices = models.Unit.get_types()          self.fields['unit'].help_text = models.Unit.get_help() +    def get_input_ids(self): +        ids = super(RecordSelect, self).get_input_ids() +        ids.pop(ids.index('parcel')) +        ids.append('parcel_0') +        ids.append('parcel_1') +        return ids +  class RecordFormSelection(forms.Form):      form_label = _("Context record search")      associated_models = {'pk':models.ContextRecord} diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index bd18ffa49..c59446bcf 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2012  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-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 @@ -30,7 +30,10 @@ get_contextrecord = get_item(models.ContextRecord,          'get_contextrecord', 'contextrecord',        extra_request_keys={'parcel__town':'parcel__town__pk',                    'operation__year':'operation__year__contains', -                  'datings__period':'datings__period__pk'},) +                  'datings__period':'datings__period__pk', +                  'parcel_0':'operation__parcels__section', +                  'parcel_1':'operation__parcels__parcel_number', +                  },)  get_contextrecordsource = get_item(models.ContextRecordSource,          'get_contextrecordsource', 'contextrecordsource',        extra_request_keys={ diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py index 564d0c6fc..ea12c984c 100644 --- a/archaeological_files/forms.py +++ b/archaeological_files/forms.py @@ -36,13 +36,14 @@ from ishtar_common.models import Person, PersonType, Town, Organization, \  from archaeological_operations.models import ActType, AdministrativeAct  import models  from ishtar_common.forms import FinalForm, FormSet, ClosingDateFormSelection, \ -    formset_factory, get_now, reverse_lazy +    formset_factory, get_now, reverse_lazy, TableSelect  from ishtar_common.forms_common import get_town_field, get_person_field  from archaeological_operations.forms import AdministrativeActOpeForm, \ -    AdministrativeActOpeFormSelection, FinalAdministrativeActDeleteForm +    AdministrativeActOpeFormSelection, FinalAdministrativeActDeleteForm, \ +    ParcelField  from ishtar_common import widgets -class FileSelect(forms.Form): +class FileSelect(TableSelect):      towns = get_town_field()      in_charge = get_person_field(label=_(u"Person in charge"),                                   person_type='sra_agent') @@ -50,12 +51,20 @@ class FileSelect(forms.Form):                                    choices=models.FileType.get_types())      saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[])      year = forms.IntegerField(label=_("Year")) +    parcel = ParcelField(label=_("Parcel (section/number)"))      def __init__(self, *args, **kwargs):          super(FileSelect, self).__init__(*args, **kwargs)          self.fields['saisine_type'].choices = models.SaisineType.get_types()          self.fields['saisine_type'].help_text = models.SaisineType.get_help() +    def get_input_ids(self): +        ids = super(FileSelect, self).get_input_ids() +        ids.pop(ids.index('parcel')) +        ids.append('parcel_0') +        ids.append('parcel_1') +        return ids +  class FileFormSelection(forms.Form):      form_label = _("Archaeological file search")      associated_models = {'pk':models.File} @@ -170,7 +179,7 @@ class FinalFileDeleteForm(FinalForm):      confirm_msg = " "      confirm_end_msg = _(u"Would you like to delete this archaelogical file ?") -class AdministrativeActFileSelect(forms.Form): +class AdministrativeActFileSelect(TableSelect):      associated_file__towns = get_town_field()      act_type = forms.ChoiceField(label=_("Act type"), choices=[]) diff --git a/archaeological_files/views.py b/archaeological_files/views.py index 3ef8c0f28..2b5003911 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2012  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-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 @@ -60,7 +60,11 @@ def autocomplete_file(request):                                            for file in files])      return HttpResponse(data, mimetype='text/plain') -get_file = get_item(models.File, 'get_file', 'file') +get_file = get_item(models.File, 'get_file', 'file', +    extra_request_keys={'parcel_0':'operations__parcels__section', +                        'parcel_1':'operations__parcels__parcel_number', +                        }, +                    )  show_file = show_item(models.File, 'file')  revert_file = revert_item(models.File) diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index c5480d8a8..feaad0e23 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -39,7 +39,7 @@ import models  from ishtar_common import widgets  from ishtar_common.forms import FinalForm, FormSet, FloatField, \ -    formset_factory, get_now, get_form_selection, reverse_lazy +    formset_factory, get_now, get_form_selection, reverse_lazy, TableSelect  from ishtar_common.forms_common import get_town_field, \      SourceForm, SourceSelect, SourceDeletionForm, AuthorFormset  from archaeological_context_records.forms import RecordFormSelection @@ -81,7 +81,7 @@ class DateForm(forms.Form):          self.fields['dating__dating_type'].choices = DatingType.get_types()          self.fields['dating__dating_type'].help_text = DatingType.get_help() -class FindSelect(forms.Form): +class FindSelect(TableSelect):      base_finds__context_record__parcel__town = get_town_field()      base_finds__context_record__operation__year = forms.IntegerField(                                                               label=_(u"Year")) diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py index 5501857ba..547daf828 100644 --- a/archaeological_operations/forms.py +++ b/archaeological_operations/forms.py @@ -35,13 +35,23 @@ from django.utils.translation import ugettext_lazy as _  from ishtar_common.models import valid_id, PersonType, Person, Town  from archaeological_files.models import File  import models +from widgets import ParcelWidget  from ishtar_common import widgets  from ishtar_common.forms import FinalForm, FormSet, ClosingDateFormSelection, \ -     formset_factory, get_now, reverse_lazy, get_form_selection +     formset_factory, get_now, reverse_lazy, get_form_selection, TableSelect  from ishtar_common.forms_common import TownForm, TownFormSet, TownFormset, \       AuthorFormset, SourceForm, SourceSelect, \       SourceDeletionForm, get_town_field +class ParcelField(forms.MultiValueField): +    def __init__(self, *args, **kwargs): +        if 'widget' not in kwargs: +            self.widget = ParcelWidget() +        return super(ParcelField, self).__init__(*args, **kwargs) + +    def compress(data_list): +        return u"-".join(data_list) +  class ParcelForm(forms.Form):      form_label = _("Parcels")      base_model = 'parcel' @@ -93,7 +103,7 @@ ParcelFormSet = formset_factory(ParcelForm, can_delete=True,                                  formset=ParcelFormSet)  ParcelFormSet.form_label = _(u"Parcels") -class OperationSelect(forms.Form): +class OperationSelect(TableSelect):      common_name = forms.CharField(label=_(u"Name"), max_length=30)      if settings.COUNTRY == 'fr':          code_patriarche = forms.IntegerField( @@ -120,6 +130,7 @@ class OperationSelect(forms.Form):                                   widget=widgets.JQueryDate)      end_after = forms.DateField(label=_(u"Ended after"),                                  widget=widgets.JQueryDate) +    parcel = ParcelField(label=_("Parcel (section/number)"))      end_date = forms.NullBooleanField(label=_(u"Is open?"))      def __init__(self, *args, **kwargs): @@ -127,6 +138,13 @@ class OperationSelect(forms.Form):          self.fields['operation_type'].choices = models.OperationType.get_types()          self.fields['operation_type'].help_text = models.OperationType.get_help() +    def get_input_ids(self): +        ids = super(OperationSelect, self).get_input_ids() +        ids.pop(ids.index('parcel')) +        ids.append('parcel_0') +        ids.append('parcel_1') +        return ids +  class OperationFormSelection(forms.Form):      form_label = _(u"Operation search")      associated_models = {'pk':models.Operation} @@ -425,7 +443,7 @@ OperationSourceFormSelection = get_form_selection(  # Administrative act management for operations #  ################################################ -class AdministrativeActOpeSelect(forms.Form): +class AdministrativeActOpeSelect(TableSelect):      operation__towns = get_town_field()      act_type = forms.ChoiceField(label=_("Act type"), choices=[]) diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index 4650e4764..84f208bf3 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -92,6 +92,14 @@ def get_available_operation_code(request, year=None):      data = json.dumps({'id':models.Operation.get_available_operation_code(year)})      return HttpResponse(data, mimetype='text/plain') +def get_parcel_parser(key_section, key_number): +    def func(dct): +        print dct +        section, number = dct.get(key_section), dct.get(key_number) +        if not section or not number: +            return {} +        return {key_section:section, key_number:number} +  get_operation = get_item(models.Operation, 'get_operation', 'operation',      bool_fields = ['end_date__isnull'],      dated_fields = ['start_date__lte', 'start_date__gte', @@ -102,7 +110,11 @@ get_operation = get_item(models.Operation, 'get_operation', 'operation',                          'start_before':'start_date__lte',                          'start_after':'start_date__gte',                          'end_before':'excavation_end_date__lte', -                        'end_after':'excavation_end_date__gte',}) +                        'end_after':'excavation_end_date__gte', +                        'parcel_0':'parcels__section', +                        'parcel_1':'parcels__parcel_number', +                        }, +    )  show_operation = show_item(models.Operation, 'operation')  revert_operation = revert_item(models.Operation) diff --git a/archaeological_operations/widgets.py b/archaeological_operations/widgets.py new file mode 100644 index 000000000..0e84b2047 --- /dev/null +++ b/archaeological_operations/widgets.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 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 +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +from django import forms +from django.forms import widgets + +class ParcelWidget(widgets.MultiWidget): +    def __init__(self, attrs=None): +        if not attrs: +            attrs = {'class':'widget-parcel'} +        elif 'class' not in attrs: +            attrs['class'] = 'widget-parcel' +        else: +            attrs['class'] += ' widget-parcel' +        _widgets = ( +            widgets.TextInput(attrs=attrs), +            widgets.TextInput(attrs=attrs), +            ) +        super(ParcelWidget, self).__init__(_widgets, attrs) + +    def decompress(self, value): +        if value: +            return value +        return [None, None] + +    def format_output(self, rendered_widgets): +        return u' / '.join(rendered_widgets) diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index 2e1bfcc05..69bb2cae3 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -27,7 +27,8 @@ from ishtar_common.models import Person, valid_id  from archaeological_finds.models import TreatmentType  import models  from ishtar_common import widgets -from ishtar_common.forms import name_validator, reverse_lazy, get_form_selection +from ishtar_common.forms import name_validator, reverse_lazy, \ +    get_form_selection, TableSelect  from archaeological_finds.forms import FindMultipleFormSelection  def get_warehouse_field(label=_(u"Warehouse"), required=True): @@ -109,7 +110,7 @@ class ContainerForm(forms.Form):          new_item.save()          return new_item -class ContainerSelect(forms.Form): +class ContainerSelect(TableSelect):      location = get_warehouse_field()      container_type = forms.ChoiceField(label=_(u"Container type"), choices=[])      reference = forms.CharField(label=_(u"Reference")) diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index d66d6d4cc..cb007442e 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2011  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-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 @@ -101,6 +101,10 @@ class FormSet(BaseFormSet):          form.fields[DELETION_FIELD_NAME].label = ''          form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget() +class TableSelect(forms.Form): +    def get_input_ids(self): +        return self.fields.keys() +  def get_now():      format = formats.get_format('DATE_INPUT_FORMATS')[0]      value = datetime.datetime.now().strftime(format) diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 34a930e36..52fcfc97a 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -37,7 +37,7 @@ from django.utils.translation import ugettext_lazy as _  import models  import widgets -from forms import FinalForm, FormSet, reverse_lazy, name_validator +from forms import FinalForm, FormSet, reverse_lazy, name_validator, TableSelect  def get_town_field(label=_(u"Town"), required=True):      help_text = _(u"<p>Type name, department code and/or postal code of the " @@ -234,7 +234,7 @@ class SourceForm(forms.Form):          super(SourceForm, self).__init__(*args, **kwargs)          self.fields['source_type'].choices = models.SourceType.get_types() -class SourceSelect(forms.Form): +class SourceSelect(TableSelect):      authors = forms.IntegerField(           widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \                       'autocomplete-author', associated_model=models.Author), diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css index 2aa673b51..cad9a224a 100644 --- a/ishtar_common/static/media/style.css +++ b/ishtar_common/static/media/style.css @@ -528,3 +528,6 @@ a.remove{      border:1px solid;  } +.widget-parcel{ +    width:60px; +} diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 83833e517..54523996f 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -173,7 +173,7 @@ HIERARCHIC_LEVELS = 5  HIERARCHIC_FIELDS = ['period', 'unit', 'material_type']  PRIVATE_FIELDS = ('id', 'history_modifier', 'order')  def get_item(model, func_name, default_name, extra_request_keys=[], -                    base_request={}, bool_fields=[], dated_fields=[]): +            base_request={}, bool_fields=[], dated_fields=[]):      """      Generic treatment of tables      """ diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index ecc48a1e8..1fd0b6ac0 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -219,8 +219,8 @@ class JQueryJqGrid(forms.RadioSelect):          rendered += "\n<h4>%s</h4>\n" % unicode(_("Search and select an item"))
          extra_cols = []
          col_names, col_idx = [], []
 -        for k in self.form.fields:
 -            field = self.form.fields[k]
 +        for k in self.form.get_input_ids():
 +            #field = self.form.fields[k]
              col_idx.append(u'"%s"' % k)
          for field_name in getattr(self.associated_model, self.table_cols):
              field = self.associated_model
 @@ -292,7 +292,7 @@ class JQueryJqGrid(forms.RadioSelect):                  }
              }
              var mygrid = jQuery("#grid_%(name)s");
 -            var url = "%(source)s?submited=1&" + data;
 +            var url = "%(source)s?submited=1&" + data;
              mygrid.setGridParam({url:url});
              mygrid.trigger("reloadGrid");
              return false;
 | 
