diff options
| -rw-r--r-- | archaeological_files_pdl/forms.py | 56 | ||||
| -rw-r--r-- | archaeological_files_pdl/templates/ishtar/wizard/wizard_instruction.html | 100 | ||||
| -rw-r--r-- | archaeological_files_pdl/templates/ishtar/wizard/wizard_preventiveplanning.html | 77 | ||||
| -rw-r--r-- | archaeological_files_pdl/views.py | 2 | ||||
| -rw-r--r-- | archaeological_files_pdl/wizards.py | 17 | ||||
| -rw-r--r-- | ishtar_common/forms_common.py | 8 | ||||
| -rw-r--r-- | ishtar_common/static/media/style.css | 4 | ||||
| -rw-r--r-- | ishtar_common/tasks.py | 35 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/JQueryAdvancedTown.html | 99 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/JQueryAdvancedTown.js | 1 | ||||
| -rw-r--r-- | ishtar_common/urls.py | 4 | ||||
| -rw-r--r-- | ishtar_common/views.py | 39 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 101 | ||||
| -rw-r--r-- | ishtar_common/wizards.py | 7 | 
14 files changed, 537 insertions, 13 deletions
diff --git a/archaeological_files_pdl/forms.py b/archaeological_files_pdl/forms.py index 2703e52fd..295edcd36 100644 --- a/archaeological_files_pdl/forms.py +++ b/archaeological_files_pdl/forms.py @@ -21,13 +21,14 @@ import datetime  from django import forms  from django.core import validators +from django.utils.safestring import mark_safe  from django.utils.translation import ugettext_lazy as _ -from ishtar_common.models import Person, valid_id +from ishtar_common.models import Person, PersonType, valid_id  from archaeological_files import models  from ishtar_common.forms import get_now, reverse_lazy -from ishtar_common.forms_common import get_town_field +from ishtar_common.forms_common import get_advanced_town_field  from archaeological_files.forms import GENERAL_CONTRACTOR, \                                         RESPONSIBLE_PLANNING_SERVICE @@ -72,11 +73,14 @@ class FileFormPlanning(forms.Form):      associated_models = {'town':models.Town}      name = forms.CharField(label=_(u"Planning name"), required=False,                             max_length=100) -    main_town = get_town_field(required=False) +    main_town = get_advanced_town_field(required=True)      locality = forms.CharField(label=_(u"Locality"), max_length=100,                                 required=False)      address = forms.CharField(label=_(u"Address (number/street)"), -                              widget=forms.Textarea, required=False) +                              widget=forms.Textarea( +                                    attrs={"placeholder":_(u"Number/street")}), +                              required=False, +                              )      postal_code = forms.CharField(label=_(u"Postal code"), max_length=10,                                    required=False)      total_surface = forms.IntegerField(required=False, @@ -156,6 +160,8 @@ class FileFormGeneralContractor(forms.Form):  class FileFormPlanningService(forms.Form):      form_label = _(u"Town planning service")      associated_models = {'responsible_planning_service':models.Person} +    reference_number = forms.IntegerField(label=_(u"File reference"), +                                          required=False)      def __init__(self, *args, **kwargs):          super(FileFormPlanningService, self).__init__(*args, **kwargs) @@ -170,4 +176,46 @@ class FileFormPlanningService(forms.Form):                  js_template='ishtar/blocks/JQueryCorporationPerson.js',                  new=True),              validators=[valid_id(Person)]) +        self.fields.keyOrder = ['responsible_planning_service', +                                'reference_number'] + +class FileFormInstruction(forms.Form): +    form_label = u"Instruction SRA" +    in_charge = forms.IntegerField(label=_("Person in charge"), +        widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person', +          args=[PersonType.objects.get(txt_idx='sra_agent').pk]), +        limit={'person_types':[PersonType.objects.get(txt_idx='sra_agent').pk]}, +        associated_model=Person, new=True), +        validators=[valid_id(Person)]) +    related_file = forms.IntegerField(label=_("Related file"), required=False, +         widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'), +                                           associated_model=models.File), +         validators=[valid_id(models.File)]) +    comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, +                              required=False) +    year = forms.IntegerField(label=_("Year"), +                              validators=[validators.MinValueValidator(1900), +                                          validators.MaxValueValidator(2100)]) +    numeric_reference = forms.IntegerField(label=_("Numeric reference"), +                                           required=False) +    end_date = forms.DateField(initial=get_now, widget=widgets.JQueryDate, +                               required=False) +    def __init__(self, *args, **kwargs): +        c_year = datetime.date.today().year +        if 'year' in kwargs: +            c_year = kwargs.pop('year') +        super(FileFormInstruction, self).__init__(*args, **kwargs) +        self.fields['year'].initial = c_year +        self.fields['year'].widget.attrs.update({'readonly':'readonly'}) +        c_num, lasts = 0, "" +        q = models.File.objects.filter(numeric_reference__isnull=False, +                        year=c_year).order_by('-numeric_reference') +        if q.count(): +            num = q.all()[0].numeric_reference +            lasts = u"SRA %s-%d" % (unicode(c_year), num) +        lbl = self.fields['numeric_reference'].label +        if lasts: +            lbl += u"<br/>(dernière entrée : %s)" % lasts +        self.fields['numeric_reference'].label = mark_safe(lbl) +        self.fields['numeric_reference'].initial = c_num + 1 diff --git a/archaeological_files_pdl/templates/ishtar/wizard/wizard_instruction.html b/archaeological_files_pdl/templates/ishtar/wizard/wizard_instruction.html new file mode 100644 index 000000000..b47de2cce --- /dev/null +++ b/archaeological_files_pdl/templates/ishtar/wizard/wizard_instruction.html @@ -0,0 +1,100 @@ +{% extends "ishtar/wizard/default_wizard.html" %} +{% load i18n range table_form %} +{% block wizard_form %} +<form action="." method="post" name='wizard'{% if wizard.form.file_upload %} enctype="multipart/form-data"{% endif %}>{% csrf_token %} +<div class='form'> +{{ wizard.form.media }} +{{ wizard.management_form }} + +<table> + +<tr class='required'> +  <th><label for="id_instruction-{{CURRENT_ACTION}}-in_charge">Dossier suivi par</label></th> +</tr> +<tr class='required'> +  <td>{{wizard.form.in_charge|safe}}</td> +</tr> + +<tr> +  <th><label for="id_instruction-{{CURRENT_ACTION}}-related_file">Dossier lié à</label></th> +</tr> +<tr> +  <td>{{wizard.form.related_file|safe}}</td> +</tr> + +<tr> +  <th><label for="id_instruction-{{CURRENT_ACTION}}-comment">Commentaire</label></th> +</tr> +<tr> +  <td>{{wizard.form.comment|safe}}</td> +</tr> + +<tr class='required'> +  <th><label>État du dossier</label></th> +</tr> +<tr> +  <td><input type='radio' name='state' value='open' id='state-open'/> <label for='state-open'>Dossier actif</label></td> +</tr> +<tr> +  <td><input type='radio' name='state' value='closed' id='state-closed'/> <label for='state-closed'>Dossier clos / date de clôture</label> : {{wizard.form.end_date|safe}}</td> +</tr> + +<tr class='required'> +  <th><label for="id_instruction-{{CURRENT_ACTION}}-year">{{wizard.form.numeric_reference.label}}</label></th> +</tr> +<tr> +  <td>SRA <span class='small'>{{wizard.form.year|safe}}</span> - <span class='small'>{{wizard.form.numeric_reference|safe}}</span></td> +</tr> +</table> + +<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> +{{ previous_fields|safe }} +<div id='validation-bar'> +  <input type="submit" id="submit_form" name='validate' value="{% trans "Validate" %}"/> +  {% if next_steps %}<input type="submit" id="submit_end_form" name='validate_and_end' value="{% trans "Validate and end" %}"/>{% endif %} +</div> +</div> +</form> +<script type='text/javascript'> +$(function(){ + +    if ($('#id_instruction-{{CURRENT_ACTION}}-end_date').val()){ +        $("#state-closed").prop('checked', true); +    } else { +        $("#state-open").prop('checked', true); +    } + +    check_state = function(){ +        var state = $("input[name=state]:checked").val(); +        if (state == 'closed'){ +            $('#id_instruction-{{CURRENT_ACTION}}-end_date').focus(); +            $('#id_instruction-{{CURRENT_ACTION}}-end_date').prop('disabled', false); +        } else if (state == 'open'){ +            $('#id_instruction-{{CURRENT_ACTION}}-end_date').val(''); +            $('#id_instruction-{{CURRENT_ACTION}}-end_date').prop('disabled', true); +        } +    }; + +    $('input[name=state]').click(check_state); + +    check_state(); + +    $('#submit_form').click(function(){ +        var state = $("input[name=state]:checked").val(); +        if (state == 'closed'){ +            if (!$('#id_instruction-{{CURRENT_ACTION}}-end_date').val()){ +                alert("Vous devez sélectionner une date de clôture.") +                return false; +            } +            return true; +        } else if (state == 'open'){ +            return true; +        } else { +            alert("Vous devez choisir un état pour ce dossier.") +            return false; +        } +        return true; +    }); +}); +</script> +{% endblock %} diff --git a/archaeological_files_pdl/templates/ishtar/wizard/wizard_preventiveplanning.html b/archaeological_files_pdl/templates/ishtar/wizard/wizard_preventiveplanning.html new file mode 100644 index 000000000..41527629d --- /dev/null +++ b/archaeological_files_pdl/templates/ishtar/wizard/wizard_preventiveplanning.html @@ -0,0 +1,77 @@ +{% extends "ishtar/wizard/default_wizard.html" %} +{% load i18n range table_form %} +{% block wizard_form %} +<form action="." method="post" name='wizard'{% if wizard.form.file_upload %} enctype="multipart/form-data"{% endif %}>{% csrf_token %} +<div class='form'> +{{ wizard.form.media }} +{{ wizard.management_form }} + +<table> + +<tr class='required'> +  <th><label for="id_preventiveplanning-{{CURRENT_ACTION}}-name">Nom de l'aménagement</label></th> +</tr> +<tr class='required'> +  <td>{{wizard.form.name|safe}}</td> +</tr> + +</table> + +<h4>Localisation</h4> +<table> + +<tr> +  <td>{{wizard.form.main_town|safe}}</td> +</tr> + +<tr> +  <th colspan='2'><label for="id_preventiveplanning-{{CURRENT_ACTION}}-locality">Lieu-dit</label></th> +</tr> +<tr> +  <td colspan='2'>{{wizard.form.locality|safe}}</td> +</tr> + +<tr> +  <th colspan='2'><label for="id_preventiveplanning-{{CURRENT_ACTION}}-address">Adresse</label></th> +</tr> +<tr> +  <td colspan='2'>{{wizard.form.address|safe}}</td> +</tr> + +<tr> +  <th colspan='2'><label for="id_preventiveplanning-{{CURRENT_ACTION}}-postal_code">Code postal</label></th> +</tr> +<tr> +  <td colspan='2'>{{wizard.form.postal_code|safe}}</td> +</tr> + +</table> + +<h4>Surfaces</h4> +<table> + +<tr> +  <th><label for="id_preventiveplanning-{{CURRENT_ACTION}}-total_surface">Surface totale des terrains</label></th> +</tr> +<tr> +  <td>{{wizard.form.total_surface|safe}}</td> +</tr> + +<tr> +  <th><label for="id_preventiveplanning-{{CURRENT_ACTION}}-total_developed_surface">Surface totale aménagée</label></th> +</tr> +<tr> +  <td>{{wizard.form.total_developed_surface|safe}}</td> +</tr> + +</table> + +<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> +{{ previous_fields|safe }} +<div id='validation-bar'> +  <input type="submit" id="submit_form" name='validate' value="{% trans "Validate" %}"/> +  {% if next_steps %}<input type="submit" id="submit_end_form" name='validate_and_end' value="{% trans "Validate and end" %}"/>{% endif %} +</div> +</div> +</form> +{% endblock %} diff --git a/archaeological_files_pdl/views.py b/archaeological_files_pdl/views.py index 712990234..c8e1d1498 100644 --- a/archaeological_files_pdl/views.py +++ b/archaeological_files_pdl/views.py @@ -39,6 +39,8 @@ file_creation_wizard = FileWizard.as_view([                                              forms.FileFormGeneralContractor),                  ('planningservice-file_creation',                                              forms.FileFormPlanningService), +                ('instruction-file_creation', +                                            forms.FileFormInstruction),                  ('research-file_creation', ref_forms.FileFormResearch),                  ('final-file_creation', ref_forms.FinalForm)],               label=_(u"New file"), diff --git a/archaeological_files_pdl/wizards.py b/archaeological_files_pdl/wizards.py index 4abe5f0d5..6f688d7ca 100644 --- a/archaeological_files_pdl/wizards.py +++ b/archaeological_files_pdl/wizards.py @@ -25,12 +25,23 @@ class FileWizard(BaseFileWizard):      town_input_id = 'main_town'      multi_towns = False      wizard_templates = { -        'generalcontractor-file_creation':\ -                    'ishtar/wizard/wizard_generalcontractor.html',} +        'generalcontractor-%(url_name)s':\ +                    'ishtar/wizard/wizard_generalcontractor.html', +        'instruction-%(url_name)s':\ +                    'ishtar/wizard/wizard_instruction.html', +        'preventiveplanning-%(url_name)s':\ +                    'ishtar/wizard/wizard_preventiveplanning.html', +                    } + +    def get_current_year(self): +        general_form_key = 'general-' + self.url_name +        return self.session_get_value(general_form_key, 'year')      def get_form_kwargs(self, *args, **kwargs):          returned = super(FileWizard, self).get_form_kwargs(*args, **kwargs) -        if args and args[0].startswith('generalcontractor-file_creation'): +        if args and args[0].startswith('generalcontractor-'):              if 'status' in self.request.GET:                  returned['status'] = self.request.GET['status'] +        if args and args[0].startswith('instruction-'): +            returned['year'] = self.get_current_year()          return returned diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index e1a0e9063..23d7126c9 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -54,6 +54,14 @@ def get_town_field(label=_(u"Town"), required=True):           validators=[models.valid_id(models.Town)], label=label,           help_text=mark_safe(help_text), required=required) +def get_advanced_town_field(label=_(u"Town"), required=True): +    # !FIXME hard_link, reverse_lazy doen't seem to work with formsets +    return forms.IntegerField( +         widget=widgets.JQueryTown("/" + settings.URL_PATH + \ +                                   'autocomplete-advanced-town'), +         validators=[models.valid_id(models.Town)], label=label, +         required=required) +  def get_person_field(label=_(u"Person"), required=True, person_types=[]):      # !FIXME hard_link, reverse_lazy doen't seem to work with formsets      widget = None diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css index 55bb95e30..a1b084002 100644 --- a/ishtar_common/static/media/style.css +++ b/ishtar_common/static/media/style.css @@ -906,6 +906,10 @@ a.remove{      width:60px;  } +.small, .small input{ +    width:60px; +} +  #progress{      display:none;      position:fixed; diff --git a/ishtar_common/tasks.py b/ishtar_common/tasks.py index a9db26087..a8db97bb1 100644 --- a/ishtar_common/tasks.py +++ b/ishtar_common/tasks.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2013 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2013-2014 É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 @@ -17,13 +17,15 @@  # See the file COPYING for details. +import sys +  from django.conf import settings  from django.db.models import Q -from geodjangofla.models import Commune -from ishtar_common.models import Town +from ishtar_common.models import Town, Department  def load_towns(): +    from geodjangofla.models import Commune      q = None      for dpt_number in settings.ISHTAR_DPTS:          query = Q(insee_com__istartswith=dpt_number) @@ -51,3 +53,30 @@ def load_towns():                  setattr(town, k, defaults[k])              town.save()      return nb, updated + +def update_towns(): +    nb, updated = 0, 0 +    dpts = dict([(dpt.number, dpt) for dpt in Department.objects.all()]) +    q = Town.objects.filter(numero_insee__isnull=False) +    total = q.count() +    for idx, town in enumerate(q.all()): +        sys.stdout.write('\rProcessing... %s/%d' % ( +                                str(idx+1).zfill(len(str(total))), total)) +        if len(town.numero_insee) < 2: +            continue +        dpt_code = town.numero_insee[:2] +        if dpt_code.startswith('9') and int(dpt_code) > 95: +            dpt_code = town.numero_insee[:3] +        if dpt_code not in dpts: +            sys.stdout.write('Missing department with INSEE code: %s' % dpt_code) +            continue +        if town.departement == dpts[dpt_code]: +            continue +        if town.departement: +            updated += 1 +        else: +            nb += 1 +        town.departement = dpts[dpt_code] +        town.save() +    sys.stdout.write('\n') +    return nb, updated diff --git a/ishtar_common/templates/blocks/JQueryAdvancedTown.html b/ishtar_common/templates/blocks/JQueryAdvancedTown.html new file mode 100644 index 000000000..78d2d7831 --- /dev/null +++ b/ishtar_common/templates/blocks/JQueryAdvancedTown.html @@ -0,0 +1,99 @@ +{% load i18n %}{% load url from future %}</td></tr> +<tr> +  <td>{% trans "State" context "Région" %}</td> +  <td> +  <select id='current-state'> +    <option value=''>--------</option>{% for state in states %} +    <option value='{{state.number}}'{% if state.number == selected_state %}selected='selected'{% endif %}>{{state}}</option> +  {% endfor %}</select> +  </td> +</tr> +<tr> +  <td>{% trans "Department" %}</td> +  <td> +  <select id='current-department'> +  </select> +  </td> +</tr> +<tr class='required'> +  <th><label>{% trans "Town" %}</label></th> +  <td><input{{attrs_select}}/> +<input type="hidden"{{attrs_hidden}}/> +<script type="text/javascript"><!--// +    selected_department = "{{selected_department}}"; +    var empty_select = "<option value=''>--------</option>"; + +    function update_department_field(){ +        var selected_state = $("#current-state").val(); +        if (!selected_state){ +            $("#current-department").html("<option value=''>"+"{% trans 'Choose a state first' %}"+"</option>"); +            $("#current-department").prop('disabled', true); +            $('#id_select_{{field_id}}').prop('disabled', true); +            return; +        } +        $.ajax({ +            url: "{% url 'department-by-state' %}" + selected_state, +            type: 'get', +            dataType: 'json', +            success: function(data) { +                var html = ""; +                for (idx in data){ +                    dpt = data[idx]; +                    html += "<option value='" + dpt.number + "'"; +                    if (String(dpt.number) == String(selected_department)){ +                        html += " selected='selected'"; +                    } +                    html += ">" + dpt.value + "</option>"; +                } +                $("#current-department").html(html); +                $("#current-department").prop('disabled', false); +                update_search_town(); +            } +        }); +    } + +    function update_search_town(){ +        selected_department = $("#current-department").val(); +        if (selected_department){ +            $("#id_select_{{field_id}}").autocomplete( "option", "source", {{source}}+selected_department); +            $('#id_select_{{field_id}}').prop('disabled', false); +        } else { +            $('#id_select_{{field_id}}').prop('disabled', true); +        } +    } + +    function empty_town(){ +        $('#id_{{field_id}}').val(null); +        $('#id_select_{{field_id}}').val(null); +    } + +    $(function() { +        update_department_field(); + +        $("#current-state").change(function(){ +            empty_town(); +            update_department_field(); +        }); + +        $("#current-department").change(function(){ +            empty_town(); +            update_search_town(); +        }); + +        $("#id_select_{{field_id}}").autocomplete({ +            source: {{source}}, +            select: function( event, ui ) { +                    if(ui.item){ +                        $('#id_{{field_id}}').val(ui.item.id); +                    } else { +                        $('#id_{{field_id}}').val(null); +                    } +                }, +            minLength: 2{% if options %}, +            {{options}} +            {% endif %} +        }); + +        $('#id_select_{{field_id}}').live('click', empty_town); + +});//--></script> diff --git a/ishtar_common/templates/blocks/JQueryAdvancedTown.js b/ishtar_common/templates/blocks/JQueryAdvancedTown.js new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ishtar_common/templates/blocks/JQueryAdvancedTown.js @@ -0,0 +1 @@ + diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index d31d0d359..0c4059eeb 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -98,8 +98,12 @@ urlpatterns += patterns('ishtar_common.views',             name='get-person'),       url(r'show-person(?:/(?P<pk>.+))?/(?P<type>.+)?$',             'show_person', name='show-person'), +     url(r'department-by-state/(?P<state_id>.+)?$', 'department_by_state', +           name='department-by-state'),       url(r'autocomplete-town/?$', 'autocomplete_town',             name='autocomplete-town'), +     url(r'autocomplete-advanced-town/(?P<department_id>[0-9]+[ABab]?)?$', +        'autocomplete_advanced_town', name='autocomplete-advanced-town'),       url(r'autocomplete-department/?$', 'autocomplete_department',             name='autocomplete-department'),       url(r'new-author/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$', diff --git a/ishtar_common/views.py b/ishtar_common/views.py index a8ab91fb9..66b488254 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -202,6 +202,45 @@ def autocomplete_town(request):                                            for town in towns])      return HttpResponse(data, mimetype='text/plain') +def autocomplete_advanced_town(request, department_id=None, state_id=None): +    if not request.GET.get('term'): +        return HttpResponse(mimetype='text/plain') +    q = request.GET.get('term') +    q = unicodedata.normalize("NFKD", q).encode('ascii','ignore') +    query = Q() +    for q in q.split(' '): +        extra = Q(name__icontains=q) +        if settings.COUNTRY == 'fr': +            extra = extra | Q(numero_insee__istartswith=q) +            if not department_id: +                extra = extra | Q(departement__label__istartswith=q) +        query = query & extra +    if department_id: +        query = query & Q(departement__number__iexact=department_id) +    if state_id: +        query = query & Q(departement__state__number__iexact=state_id) +    limit = 20 +    towns = models.Town.objects.filter(query)[:limit] +    result = [] +    for town in towns: +        val = town.name +        if hasattr(town, 'numero_insee'): +            val += " (%s)" % town.numero_insee +        result.append({'id':town.pk, 'value':val}) +    data = json.dumps(result) +    return HttpResponse(data, mimetype='text/plain') + +def department_by_state(request, state_id=''): +    if not state_id: +        data = [] +    else: +        departments = models.Department.objects.filter(state__number=state_id) +        data = json.dumps([{'id':department.pk, 'number':department.number, +                            'value':unicode(department)} +                                          for department in departments]) +    return HttpResponse(data, mimetype='text/plain') + +  from types import NoneType  def format_val(val): diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 91594edbd..ba7e61e46 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -34,7 +34,7 @@ from django.utils.safestring import mark_safe  from django.utils.simplejson import JSONEncoder  from django.utils.translation import ugettext_lazy as _ -import models +from ishtar_common import models  reverse_lazy = lazy(reverse, unicode) @@ -283,6 +283,105 @@ class JQueryAutoComplete(forms.TextInput):          }          return html +class JQueryTown(forms.TextInput): +    """ +    Town fields whith state and department pre-selections +    """ + +    def __init__(self, source, options={}, +                 attrs={}, new=False, limit={}): +        self.options = None +        self.attrs = {} +        self.source = source +        if len(options) > 0: +            self.options = JSONEncoder().encode(options) +        self.attrs.update(attrs) +        self.new = new +        self.limit = limit + +    @classmethod +    def encode_source(cls, source): +        encoded_src = '' +        if isinstance(source, list): +            encoded_src = JSONEncoder().encode(source) +        elif isinstance(source, str) \ +           or isinstance(source, unicode): +            src = escape(source) +            if not src.endswith('/'): +                src += "/" +            encoded_src = "'%s'" % src +        else: +            try: +                src = unicode(source) +                if not src.endswith('/'): +                    src += "/" +                encoded_src = "'%s'" % src +            except: +                raise ValueError('source type is not valid') +        return encoded_src + +    def render(self, name, value=None, attrs=None): +        attrs_hidden = self.build_attrs(attrs, name=name) +        attrs_select = self.build_attrs(attrs) +        attrs_select['placeholder'] = _(u"Search...") +        selected = '' +        selected_state = '' +        selected_department = '' +        if value: +            hiddens = [] +            selects = [] +            if type(value) not in (list, tuple): +                values = unicode(escape(smart_unicode(value))) +                values = values.replace('[', '').replace(']', '') +                values = values.split(',') +            else: +                values = [] +                for v in value: +                    values += v.split(',') +            for v in values: +                if not v: +                    continue +                hiddens.append(v) +                selects.append(v) +                try: +                    item = models.Town.objects.get(pk=v) +                    selects[-1] = unicode(item) +                    if item.departement: +                        selected_department = item.departement.number +                        if item.departement.state: +                            selected_state = item.departement.state.number +                    selected = item.pk +                except (models.Town.DoesNotExist, ValueError): +                    selects.pop() +                    hiddens.pop() +            if hiddens and selects: +                attrs_hidden['value'] = hiddens[0] +                attrs_select['value'] = selects[0] +        if not self.attrs.has_key('id'): +            attrs_hidden['id'] = 'id_%s' % name +            attrs_select['id'] = 'id_select_%s' % name +        if 'class' not in attrs_select: +            attrs_select['class'] = 'autocomplete' + +        source = self.encode_source(self.source) +        dct = {'source':mark_safe(source), +               'selected':selected, +               'safe_field_id':slugify(name).replace('-', '_'), +               'field_id':name} +        if self.options: +            dct['options'] = mark_safe('%s' % self.options) + +        dct.update({'attrs_select':mark_safe(flatatt(attrs_select)), +               'attrs_hidden':mark_safe(flatatt(attrs_hidden)), +               'name':name, +               'states':models.State.objects.all().order_by('label'), +               'selected_department':selected_department, +               'selected_state':selected_state +               }) +        html = loader.get_template('blocks/JQueryAdvancedTown.html').render( +                                                                Context(dct)) +        return html +  class JQueryPersonOrganization(forms.TextInput):      """      Complex widget which manage: diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 190a7fc86..2ad3635d7 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -95,8 +95,11 @@ class Wizard(NamedUrlWizardView):      def get_template_names(self):          templates = ['ishtar/wizard/default_wizard.html']          current_step = self.steps.current -        if current_step in self.wizard_templates: -            templates = [self.wizard_templates[current_step]] + templates +        wizard_templates = dict([ +            (key % {'url_name':self.url_name}, self.wizard_templates[key]) +                            for key in self.wizard_templates]) +        if current_step in wizard_templates: +            templates = [wizard_templates[current_step]] + templates          elif current_step == self.steps.last:              templates = ['ishtar/wizard/confirm_wizard.html'] + templates          return templates  | 
