summaryrefslogtreecommitdiff
path: root/chimere
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-11-26 19:50:43 +0100
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-11-26 19:50:43 +0100
commit43b0c50accfa1017ee323ba121ac53920d1cdbf5 (patch)
tree9f554b2e55dfa8a36209363c82ddaa4915c3448f /chimere
parentf769930eca0a0bbccf991e52c6c6abbba6414390 (diff)
parenta95b7d7e58b6d8e0847b9a49e3afe0ac7a939a39 (diff)
downloadChimère-43b0c50accfa1017ee323ba121ac53920d1cdbf5.tar.bz2
Chimère-43b0c50accfa1017ee323ba121ac53920d1cdbf5.zip
Merge branch 'master' into saclay
Conflicts: chimere/admin.py chimere/fixtures/initial_data.json chimere/forms.py chimere/locale/fr/LC_MESSAGES/django.po chimere/static/chimere/css/styles.css chimere/templates/chimere/blocks/alternate_multimedia.html chimere/templates/chimere/blocks/categories.html chimere/widgets.py
Diffstat (limited to 'chimere')
-rw-r--r--chimere/admin.py129
-rw-r--r--chimere/fixtures/initial_data.json67
-rw-r--r--chimere/forms.py68
-rw-r--r--chimere/locale/fr/LC_MESSAGES/django.po633
-rw-r--r--chimere/migrations/0038_osm_import_filtr.py (renamed from chimere/migrations/0048_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py)42
-rw-r--r--chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py252
-rw-r--r--chimere/models.py77
-rw-r--r--chimere/static/chimere/css/forms.css44
-rw-r--r--chimere/static/chimere/css/styles.css4
-rw-r--r--chimere/static/chimere/js/importer_interface.js81
-rw-r--r--chimere/tasks.py14
-rw-r--r--chimere/templates/admin/chimere/managed_modified.html (renamed from chimere/templates/admin/managed_modified.html)0
-rw-r--r--chimere/templates/admin/chimere/osm_export.html31
-rw-r--r--chimere/templates/admin/chimere/propertymodel/change_form.html7
-rw-r--r--chimere/templates/chimere/blocks/alternate_multimedia.html1
-rw-r--r--chimere/templates/chimere/blocks/categories.html58
-rw-r--r--chimere/templates/chimere/blocks/inline_formset.html23
-rw-r--r--chimere/templates/chimere/feeds/rss.html4
-rw-r--r--chimere/templates/chimere/main_map.html1
-rw-r--r--chimere/tests.py64
-rw-r--r--chimere/tests/data_license1
-rw-r--r--chimere/tests/eqs7day-M5.xml42
-rw-r--r--chimere/tests/georss_simple.xml (renamed from chimere/tests/georss.xml)0
-rw-r--r--chimere/urls.py2
-rw-r--r--chimere/utils.py45
-rw-r--r--chimere/views.py14
-rw-r--r--chimere/widgets.py178
27 files changed, 1432 insertions, 450 deletions
diff --git a/chimere/admin.py b/chimere/admin.py
index ad24706..833ba9d 100644
--- a/chimere/admin.py
+++ b/chimere/admin.py
@@ -37,7 +37,7 @@ except ImportError:
pass
from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\
- NewsAdminForm, CategoryAdminForm, ImporterAdminForm,\
+ NewsAdminForm, CategoryAdminForm, ImporterAdminForm, OSMForm, \
PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm
from chimere.models import Category, Icon, SubCategory, Marker, \
PropertyModel, News, Route, Area, ColorTheme, Color, \
@@ -112,14 +112,32 @@ def managed_modified(modeladmin, request, queryset):
if request.POST.get('rapprochement'):
couple = [(item, item_ref)]
if hasattr(item, 'associated_marker'):
- couple.append((item.associated_marker, item_ref.associated_marker))
- for it, it_ref in couple:
- for k in request.POST:
+ couple.append((item.associated_marker.all()[0],
+ item_ref.associated_marker.all()[0]))
+ updated_keys = dict(request.POST)
+ # clean
+ for k in ('action', 'rapprochement', 'index', '_selected_action'):
+ if k in updated_keys:
+ updated_keys.pop(k)
+ for idx, cpl in enumerate(couple):
+ it, it_ref = cpl
+ # don't copy geometry of associated items
+ if idx:
+ for k in ('route', 'point'):
+ if k in updated_keys:
+ updated_keys.pop(k)
+ for k in updated_keys:
if not request.POST[k]:
continue
if hasattr(it_ref, k):
- setattr(it_ref, k, getattr(it, k))
- it_ref.save()
+ c_value = getattr(it_ref, k)
+ if hasattr(c_value, 'select_related'):
+ c_value.clear()
+ for val in getattr(it, k).all():
+ c_value.add(val)
+ else:
+ setattr(it_ref, k, getattr(it, k))
+ it_ref.save()
elif k.startswith('property_'):
try:
pm = PropertyModel.get(pk=int(k[len('property_'):]))
@@ -132,7 +150,7 @@ def managed_modified(modeladmin, request, queryset):
item.delete()
messages.success(request, _(u"Modified item traited."))
return HttpResponseRedirect(request.get_full_path())
- return render_to_response('admin/managed_modified.html',
+ return render_to_response('admin/chimere/managed_modified.html',
{'item':item, 'item_ref':item_ref},
context_instance=RequestContext(request))
managed_modified.short_description = _(u"Managed modified items")
@@ -165,8 +183,39 @@ class MarkerAdmin(admin.ModelAdmin):
readonly_fields = ['submiter_email', 'submiter_comment', 'import_source',
'submiter_name', 'ref_item', 'modified_since_import']
form = MarkerAdminForm
+ fieldsets = ((None, {
+ 'fields': ['point', 'name', 'status', 'categories',
+ 'description', 'start_date', 'end_date']
+ }),
+ (_(u"Submitter"), {
+ 'classes':('collapse',),
+ 'fields': ('submiter_name', 'submiter_email',
+ 'submiter_comment')
+ }),
+ (_(u"Import"), {
+ 'classes':('collapse',),
+ 'fields': ('modified_since_import', 'import_source',
+ 'origin', 'license')
+ }),
+ (_(u"Advanced options"), {
+ 'classes':('collapse',),
+ 'fields': ('ref_item', 'route',)
+ }),
+ )
inlines = [MultimediaInline, PictureInline]
+ def __init__(self, *args, **kwargs):
+ """
+ Manage properties in fieldsets.
+ """
+ main_fields = self.fieldsets[0][1]['fields']
+ for pm in PropertyModel.objects.filter(available=True).order_by('order'
+ ).all():
+ pm_name = pm.getNamedId()
+ if pm_name not in main_fields:
+ main_fields.append(pm_name)
+ super(MarkerAdmin, self).__init__(*args, **kwargs)
+
def queryset(self, request):
qs = self.model._default_manager.get_query_set()
if not request.user.is_superuser:
@@ -192,6 +241,26 @@ class RouteAdmin(admin.ModelAdmin):
readonly_fields = ('associated_file',)
actions = [validate, disable, managed_modified, export_to_kml,
export_to_shapefile, export_to_csv]
+ fieldsets = ((None, {
+ 'fields': ['route', 'name', 'status', 'categories',
+ 'start_date', 'end_date']
+ }),
+ (_(u"Submitter"), {
+ 'classes':('collapse',),
+ 'fields': ('submiter_name', 'submiter_email',
+ 'submiter_comment')
+ }),
+ (_(u"Import"), {
+ 'classes':('collapse',),
+ 'fields': ('modified_since_import', 'import_source',
+ 'origin', 'license')
+ }),
+ (_(u"Advanced options"), {
+ 'classes':('collapse',),
+ 'fields': ('ref_item', 'associated_file',
+ 'has_associated_marker')
+ }),
+ )
def queryset(self, request):
qs = self.model._default_manager.get_query_set()
@@ -239,11 +308,44 @@ def cancel_export(modeladmin, request, queryset):
cancel_export.short_description = _(u"Cancel export")
def export_to_osm(modeladmin, request, queryset):
- importers = modeladmin.model.objects.filter(importer_type='OSM')
- for importer in queryset:
- importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0])
- importer.save()
- tasks.exporting(importer.pk)
+ if queryset.count() > 1:
+ messages.error(request, _(u"Can manage only one OSM export at a time."))
+ return HttpResponseRedirect(request.get_full_path())
+ importer = queryset.all()[0]
+ if Marker.objects.filter(categories__in=importer.categories.all(),
+ status='I').count():
+ messages.error(request, _(u"You must treat all item with the status "\
+ u"\"imported\" before exporting to OSM."))
+ return HttpResponseRedirect(request.get_full_path())
+ if importer.importer_type != 'OSM':
+ messages.error(request, _(u"Only OSM importer are managed for export."))
+ return HttpResponseRedirect(request.get_full_path())
+ item_nb = Marker.objects.filter(status='A',
+ categories=importer.categories.all(),
+ not_for_osm=False, modified_since_import=True,
+ route=None).count()
+ if not item_nb:
+ messages.error(request, _(u"No point of interest are concerned by this "
+ u"export."))
+ return HttpResponseRedirect(request.get_full_path())
+ form = None
+ if request.method == 'POST' and (
+ 'email' in request.POST or 'api' in request.POST
+ or 'password' in request.POST):
+ form = OSMForm(request.POST)
+ if form.is_valid():
+ importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0])
+ importer.save()
+ tasks.exporting(importer.pk, form.cleaned_data)
+ messages.success(request, _(u"Export launched."))
+ return HttpResponseRedirect(request.get_full_path())
+ else:
+ form = OSMForm()
+ msg_item = _(u"%s point(s) of interest concerned by this export before "\
+ u"bounding box filter.") % item_nb
+ return render_to_response('admin/chimere/osm_export.html', {'item':importer,
+ 'form':form, 'msg_item':msg_item},
+ context_instance=RequestContext(request))
export_to_osm.short_description = _(u"Export to osm")
class ImporterAdmin(admin.ModelAdmin):
@@ -305,7 +407,8 @@ admin.site.register(Category, CategoryAdmin)
admin.site.register(Icon, IconAdmin)
admin.site.register(Marker, MarkerAdmin)
admin.site.register(Route, RouteAdmin)
-admin.site.register(PropertyModel, PropertyModelAdmin)
+if not settings.CHIMERE_HIDE_PROPERTYMODEL:
+ admin.site.register(PropertyModel, PropertyModelAdmin)
admin.site.register(Area, AreaAdmin)
admin.site.register(ColorTheme, ColorThemeAdmin)
admin.site.register(Layer)
diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json
index 20347a3..222c81c 100644
--- a/chimere/fixtures/initial_data.json
+++ b/chimere/fixtures/initial_data.json
@@ -1,16 +1,5 @@
[
{
- "pk": 7,
- "model": "chimere.multimediatype",
- "fields": {
- "available": true,
- "media_type": "V",
- "iframe": false,
- "name": "Matroska (mkv)",
- "mime_type": "video/x-matroska"
- }
- },
- {
"pk": 1,
"model": "chimere.multimediatype",
"fields": {
@@ -55,28 +44,6 @@
}
},
{
- "pk": 4,
- "model": "chimere.multimediatype",
- "fields": {
- "available": true,
- "media_type": "V",
- "iframe": false,
- "name": "MPEG-1 (mpg, mpeg)",
- "mime_type": "video/mpeg"
- }
- },
- {
- "pk": 8,
- "model": "chimere.multimediatype",
- "fields": {
- "available": true,
- "media_type": "V",
- "iframe": false,
- "name": "AVI - xvid, mp3 (avi)",
- "mime_type": "video/msvideo; codecs='xvid,mp3'"
- }
- },
- {
"pk": 6,
"model": "chimere.multimediatype",
"fields": {
@@ -176,14 +143,6 @@
}
},
{
- "pk": 1,
- "model": "chimere.multimediaextension",
- "fields": {
- "multimedia_type": 7,
- "name": "mkv"
- }
- },
- {
"pk": 3,
"model": "chimere.multimediaextension",
"fields": {
@@ -208,30 +167,6 @@
}
},
{
- "pk": 6,
- "model": "chimere.multimediaextension",
- "fields": {
- "multimedia_type": 4,
- "name": "mpg"
- }
- },
- {
- "pk": 7,
- "model": "chimere.multimediaextension",
- "fields": {
- "multimedia_type": 4,
- "name": "mpeg"
- }
- },
- {
- "pk": 8,
- "model": "chimere.multimediaextension",
- "fields": {
- "multimedia_type": 8,
- "name": "avi"
- }
- },
- {
"pk": 9,
"model": "chimere.multimediaextension",
"fields": {
@@ -259,7 +194,7 @@
"pk": 1,
"model": "chimere.layer",
"fields": {
- "layer_code": "new OpenLayers.Layer.OSM.Mapnik(\"Default\",\r\n{attribution:\"\", keyid:\"mapnik\", displayOutsideMaxExtent:!0,wrapDateLine:!0,layerCode:\"M\"})",
+ "layer_code": "new OpenLayers.Layer.OSM.Mapnik(\"Mapnik OSM\",\r\n{attribution:\"\", keyid:\"mapnik\", displayOutsideMaxExtent:!0,wrapDateLine:!0,layerCode:\"M\"})",
"name": "OSM - Mapnik"
}
},
diff --git a/chimere/forms.py b/chimere/forms.py
index be68205..db084f0 100644
--- a/chimere/forms.py
+++ b/chimere/forms.py
@@ -37,7 +37,7 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\
MultimediaExtension, Page
from chimere.widgets import AreaField, PointField, TextareaWidget, \
FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget, \
- TextareaAdminWidget
+ TextareaAdminWidget, ImportFiltrWidget, ImporterChoicesWidget, RE_XAPI
from datetime import timedelta, datetime, tzinfo
@@ -110,6 +110,23 @@ class PageAdminForm(forms.ModelForm):
class Meta:
model = Page
+class OSMForm(forms.Form):
+ """
+ OSM export form
+ """
+ username = forms.CharField(label=_("OSM user"))
+ password = forms.CharField(label=_(u"Password"),
+ widget=forms.PasswordInput(render_value=False))
+ # API URL are hardcoded: the day the API change Chimère will need
+ # adaptations not only on this portion...
+ api = forms.ChoiceField(label=_(u"API"),
+ choices=(('', '--'),
+ ('api06.dev.openstreetmap.org',
+ _(u"Test API - %s") % 'api06.dev.openstreetmap.org'),
+ ('api.openstreetmap.org/api',
+ _(u"Main API - %s") % 'api.openstreetmap.org/api'),
+ ))
+
class NewsAdminForm(forms.ModelForm):
"""
Main form for news
@@ -119,6 +136,9 @@ class NewsAdminForm(forms.ModelForm):
model = News
class ImporterAdminForm(forms.ModelForm):
+ filtr = forms.CharField(widget=ImportFiltrWidget, required=False)
+ importer_type = forms.ChoiceField(widget=ImporterChoicesWidget,
+ choices=[('', '--')]+list(IMPORTER_CHOICES))
class Meta:
model = Importer
widgets = {
@@ -131,6 +151,14 @@ class ImporterAdminForm(forms.ModelForm):
Verify that only one type of source is provided
Verify that shapefiles are zipped
'''
+ if self.cleaned_data.get('importer_type') == 'OSM' and \
+ not self.cleaned_data.get('filtr'):
+ raise forms.ValidationError(_(u"For OSM import you must be "\
+ u"provide a filter. Select an area and node/way filter."))
+ if self.cleaned_data.get('importer_type') == 'OSM' and \
+ not RE_XAPI.match(self.cleaned_data.get('filtr')):
+ raise forms.ValidationError(_(u"For OSM import you must be "\
+ u"provide a filter. Select an area and node/way filter."))
if self.cleaned_data.get('importer_type') == 'SHP' and \
not self.cleaned_data.get('zipped'):
raise forms.ValidationError(_(u"Shapefiles must be provided in a "\
@@ -358,13 +386,20 @@ class RouteForm(RouteAdminForm):
Custom save method in order to manage associated marker and file
"""
new_route = super(RouteForm, self).save(*args, **keys)
+ if new_route.status == 'S':
+ new_route.has_associated_marker = True
+ new_route.save()
# associate a route file
if 'associated_file_id' in self.cleaned_data and \
self.cleaned_data['associated_file_id']:
file_pk = int(self.cleaned_data['associated_file_id'])
new_route.associated_file = RouteFile.objects.get(pk=file_pk)
new_route.save()
- new_marker = Marker.objects.get(route=new_route)
+ # change the associated marker (if available)
+ q_new_marker = Marker.objects.filter(route=new_route)
+ if not q_new_marker.count():
+ return new_route
+ new_marker = q_new_marker.all()[0]
# save description
if self.cleaned_data['description']:
new_marker.description = self.cleaned_data['description']
@@ -417,6 +452,11 @@ class MultimediaFileAdminForm(forms.ModelForm):
'%schimere/js/menu-sort.js' % settings.STATIC_URL,
]
+ def __init__(self, *args, **kwargs):
+ super(MultimediaFileAdminForm, self).__init__(*args, **kwargs)
+ self.fields['multimedia_type'].widget.choices = \
+ MultimediaType.get_tuples()
+
class MultimediaFileForm(BaseFileForm):
"""
Form for a multimedia file
@@ -433,30 +473,6 @@ class MultimediaFileForm(BaseFileForm):
# this can be auto detect
self.fields['multimedia_type'].required = False
- def clean(self):
- if not self.cleaned_data.get('url'):
- return self.cleaned_data
- if self.cleaned_data.get('multimedia_type') and \
- self.cleaned_data['multimedia_type'].name != 'auto':
- return self.cleaned_data
- url = self.cleaned_data['url']
- for mm_type in IFRAME_LINKS:
- res, embeded_url = IFRAME_LINKS[mm_type]
- if [r for r in res if r.search(url)]:
- multimedia_type = MultimediaType.objects.get(
- name__iexact=mm_type)
- self.cleaned_data['multimedia_type'] = multimedia_type
- return self.cleaned_data
- ext = url.split(".")[-1]
- q = MultimediaExtension.objects.filter(name__iendswith=ext)
- if q.count():
- self.cleaned_data['multimedia_type'] = q.all()[0].multimedia_type
- else:
- # default to an iframe
- self.cleaned_data['multimedia_type'] = \
- MultimediaType.objects.filter(name__iexact='iframe').all()[0]
- return self.cleaned_data
-
MultimediaFileFormSet = formset_factory(MultimediaFileForm, can_delete=True)
class PictureFileAdminForm(forms.ModelForm):
diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po
index 5a1247c..77a7d19 100644
--- a/chimere/locale/fr/LC_MESSAGES/django.po
+++ b/chimere/locale/fr/LC_MESSAGES/django.po
@@ -7,17 +7,17 @@ msgid ""
msgstr ""
"Project-Id-Version: 2.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-11 17:48+0100\n"
+"POT-Creation-Date: 2012-11-26 19:26+0100\n"
"Last-Translator: Étienne Loks <etienne.loks@peacefrogs.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: __init__.py:8 models.py:759
+#: __init__.py:8 models.py:763
msgid "Multimedia files"
msgstr "Fichiers multimedias"
-#: __init__.py:9 models.py:815
+#: __init__.py:9 models.py:835
msgid "Picture files"
msgstr "Fichiers d'image"
@@ -45,35 +45,95 @@ msgstr "Flux RSS"
msgid "Contact us"
msgstr "Nous contacter"
-#: admin.py:53 templates/chimere/feeds/rss.html:70
+#: admin.py:59
+msgid "Disable"
+msgstr "Désactiver"
+
+#: admin.py:65 templates/admin/chimere/managed_modified.html:44
+#: templates/chimere/feeds/rss.html:70
msgid "Validate"
msgstr "Valider"
-#: admin.py:64
+#: admin.py:76
msgid "Export to KML"
msgstr "Exporter en KML"
-#: admin.py:78
+#: admin.py:90
msgid "Export to Shapefile"
msgstr "Exporter en Shapefile"
-#: admin.py:88
+#: admin.py:100
msgid "Export to CSV"
msgstr "Exporter en CSV"
-#: admin.py:174
+#: admin.py:104
+msgid "Only one item can be managed at a time."
+msgstr "Seul un élément à la fois peut-être géré."
+
+#: admin.py:113
+msgid "No modified item associated to the selected item."
+msgstr "Pas d'élément modifié associé à l'élément sélectionné."
+
+#: admin.py:156
+msgid "Modified item traited."
+msgstr "Modifié depuis le dernier import"
+
+#: admin.py:161
+msgid "Managed modified items"
+msgstr "Gérer les éléments modifiés"
+
+#: admin.py:195 admin.py:253
+msgid "Submitter"
+msgstr "Demandeur"
+
+#: admin.py:200 admin.py:258 admin.py:301
msgid "Import"
msgstr "Import"
-#: admin.py:180
+#: admin.py:205 admin.py:263
+msgid "Advanced options"
+msgstr "Options avancées"
+
+#: admin.py:307
msgid "Cancel import"
msgstr "Annuler l'import"
-#: admin.py:186
+#: admin.py:313
msgid "Cancel export"
msgstr "Annuler l'export"
-#: admin.py:194
+#: admin.py:317
+msgid "Can manage only one OSM export at a time."
+msgstr "Ne peux gérer qu'un seul export OSM à la fois."
+
+#: admin.py:322
+msgid ""
+"You must treat all item with the status \"imported\" before exporting to OSM."
+msgstr ""
+"Vous devez traiter tous les éléments avec le status « importé » avant "
+"d'exporter vers OSM."
+
+#: admin.py:326
+msgid "Only OSM importer are managed for export."
+msgstr "Seul les imports de type OSM peuvent être gérés pour les exports."
+
+#: admin.py:333
+msgid "No point of interest are concerned by this export."
+msgstr "Aucun point d'intérêt n'est concerné par cet export."
+
+#: admin.py:345
+msgid "Export launched."
+msgstr "Export lancé."
+
+#: admin.py:349
+#, python-format
+msgid ""
+"%s point(s) of interest concerned by this export before bounding box filter."
+msgstr ""
+"%s point(s) d'intérêt concerné par cet export (avant le filtre sur la "
+"zone)"
+
+#: admin.py:354
msgid "Export to osm"
msgstr "Exporter vers osm"
@@ -89,84 +149,124 @@ msgstr "Nouveaux points d'intérêt de "
msgid "Last points of interest by area"
msgstr "Nouveaux points d'intérêt par zone"
-#: forms.py:83
+#: forms.py:90
msgid "New submission for"
msgstr "Nouvelle proposition pour"
-#: forms.py:84
+#: forms.py:91
#, python-format
msgid "The new item \"%s\" has been submited in the category: "
msgstr "Le nouvel élément « %s » a été proposé dans la catégorie : "
-#: forms.py:86
+#: forms.py:93
msgid "To valid, precise or unvalid this item: "
msgstr "Pour valider, préciser ou rejeter cet élément : "
-#: forms.py:96
+#: forms.py:103
msgid "Email (optional)"
msgstr "Courriel (optionnel) "
-#: forms.py:97
+#: forms.py:104
msgid "Object"
msgstr "Objet"
-#: forms.py:136
+#: forms.py:125
+msgid "OSM user"
+msgstr "Utilisateur OSM"
+
+#: forms.py:126 models.py:1452
+msgid "Password"
+msgstr "Mot de passe"
+
+#: forms.py:130
+msgid "API"
+msgstr "API"
+
+#: forms.py:133
+#, python-format
+msgid "Test API - %s"
+msgstr "API de test - %s"
+
+#: forms.py:135
+#, python-format
+msgid "Main API - %s"
+msgstr "API principale - %s"
+
+#: forms.py:165 forms.py:169
+msgid ""
+"For OSM import you must be provide a filter. Select an area and node/way "
+"filter."
+msgstr ""
+"Pour les imports OSM vous devez fournir un filtre. Sélectionnez une zone et "
+"un filtre sur les nœuds/routes."
+
+#: forms.py:173
msgid "Shapefiles must be provided in a zipped archive."
msgstr ""
"Les fichiers Shapefiles doivent être fournis regroupés dans une archive zip."
-#: forms.py:140
+#: forms.py:177
msgid "You have to set \"source\" or \"source file\" but not both."
msgstr ""
"Vous devez spécifier le champ « Source » ou « Fichier source » mais pas les "
"deux."
-#: forms.py:145
+#: forms.py:182
msgid "You have to set \"source\" or \"source file\"."
msgstr "Vous devez spécifier le champ « Source » ou « Fichier source »."
-#: forms.py:206
+#: forms.py:243
msgid "End date has been set with no start date"
msgstr "Une date de fin a été donnée sans date de début"
-#: forms.py:210
+#: forms.py:247
msgid "End date can't be before start date"
msgstr "La date de fin ne peut pas être antérieure à la date de début"
-#: forms.py:220
+#: forms.py:257
msgid "This field is mandatory for the selected categories"
msgstr "Ce champ est obligatoire pour les catégories sélectionnées"
-#: forms.py:483
+#: forms.py:535
msgid "File"
msgstr "Fichier"
-#: forms.py:489
+#: forms.py:541
msgid "Bad file format: this must be a GPX or KML file"
msgstr "Mauvais format de fichier : KML et GPX sont supportés"
-#: forms.py:494 models.py:53 models.py:101 models.py:163 models.py:184
-#: models.py:197 models.py:212 models.py:361 models.py:693 models.py:749
-#: models.py:792 models.py:908 models.py:1224 models.py:1236 models.py:1409
-#: utils.py:458 templates/chimere/edit.html:39
-#: templates/chimere/edit_route.html:36
+#: forms.py:546 models.py:53 models.py:101 models.py:163 models.py:184
+#: models.py:197 models.py:212 models.py:362 models.py:697 models.py:753
+#: models.py:812 models.py:928 models.py:1257 models.py:1269 models.py:1442
+#: utils.py:465 templates/admin/chimere/managed_modified.html:23
+#: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36
#: templates/chimere/blocks/alternate_multimedia.html:39
msgid "Name"
msgstr "Nom"
-#: forms.py:503 models.py:1273
+#: forms.py:555 models.py:1306
msgid "Area"
msgstr "Zone"
-#: forms.py:563
+#: forms.py:595
+msgid "No area selected."
+msgstr "Pas de zone sélectionnée."
+
+#: forms.py:602
+#, python-format
+msgid "The area \"%s\" has the same order, you need to choose another one."
+msgstr ""
+"La zone « %s » a le même numéro d'ordre, vous devez un choisir un autre."
+
+#: forms.py:647
msgid "Start"
msgstr "Départ"
-#: forms.py:564
+#: forms.py:648
msgid "Finish"
msgstr "Arrivée :"
-#: forms.py:565
+#: forms.py:649
msgid "Speed"
msgstr "Vitesse"
@@ -174,13 +274,13 @@ msgstr "Vitesse"
msgid "Mnemonic"
msgstr "Mnémonique"
-#: models.py:56 models.py:102 models.py:185 models.py:213 models.py:372
-#: models.py:697 models.py:1242 models.py:1411 models.py:1452
+#: models.py:56 models.py:102 models.py:185 models.py:213 models.py:373
+#: models.py:701 models.py:1275 models.py:1444 models.py:1485
msgid "Available"
msgstr "Disponible"
-#: models.py:57 models.py:173 models.py:186 models.py:230 models.py:751
-#: models.py:807 models.py:1241 models.py:1398 models.py:1410
+#: models.py:57 models.py:173 models.py:186 models.py:230 models.py:755
+#: models.py:827 models.py:1274 models.py:1431 models.py:1443
msgid "Order"
msgstr "Ordre"
@@ -196,11 +296,11 @@ msgstr "Page"
msgid "Is front page"
msgstr "Est en page principale"
-#: models.py:105 models.py:1420
+#: models.py:105 models.py:1453
msgid "Date"
msgstr "Date"
-#: models.py:107 models.py:750
+#: models.py:107 models.py:754
msgid "Url"
msgstr "Url"
@@ -237,16 +337,16 @@ msgstr "Couleur"
msgid "Category"
msgstr "Catégorie"
-#: models.py:198 models.py:689 models.py:793 models.py:974
+#: models.py:198 models.py:693 models.py:813 models.py:994
#: templates/chimere/blocks/alternate_multimedia.html:43
msgid "Image"
msgstr "Image"
-#: models.py:200 models.py:795 models.py:976
+#: models.py:200 models.py:815 models.py:996
msgid "Height"
msgstr "Hauteur"
-#: models.py:201 models.py:796 models.py:977
+#: models.py:201 models.py:816 models.py:997
msgid "Width"
msgstr "Largeur"
@@ -262,7 +362,7 @@ msgstr "Disponible pour proposition"
msgid "Marker"
msgstr "Point d'intérêt"
-#: models.py:217 models.py:970 models.py:985
+#: models.py:217 models.py:990 models.py:1007
#: templates/chimere/edit_route.html:27
msgid "Route"
msgstr "Trajet"
@@ -303,103 +403,111 @@ msgstr "Sous-catégories"
msgid "Importer type"
msgstr "Type d'import"
-#: models.py:323 models.py:383
-msgid "Source"
-msgstr "Source"
+#: models.py:322
+msgid "Filter"
+msgstr "Filtre"
-#: models.py:325
+#: models.py:324 templates/chimere/blocks/alternate_multimedia.html:49
+msgid "Web address"
+msgstr "Adresse web"
+
+#: models.py:326
msgid "Source file"
msgstr "Fichier source"
-#: models.py:327
-msgid "Filter"
-msgstr "Filtre"
-
-#: models.py:329
+#: models.py:328
msgid "Name by default"
msgstr "Nom par défaut"
-#: models.py:331
+#: models.py:330
msgid "SRID"
msgstr "SRID"
-#: models.py:332
+#: models.py:331
msgid "Zipped file"
msgstr "Fichier zippé"
-#: models.py:333 models.py:389
+#: models.py:332 models.py:390
msgid "Origin"
msgstr "Origine"
-#: models.py:335 models.py:391
+#: models.py:334 models.py:392
msgid "License"
msgstr "Licence"
-#: models.py:338
+#: models.py:337
msgid "Associated subcategories"
msgstr "Sous-catégories associées"
-#: models.py:339 utils.py:462
+#: models.py:338 utils.py:469
msgid "State"
msgstr "État"
-#: models.py:343
+#: models.py:340
+msgid "Automatically associate a marker to a way"
+msgstr "Associer automatiquement un marqueur à une route"
+
+#: models.py:344
msgid "Importer"
msgstr "Import"
-#: models.py:363
+#: models.py:364
msgid "Submitter session key"
msgstr "Clé de session du demandeur"
-#: models.py:365
+#: models.py:366
msgid "Submitter name or nickname"
msgstr "Nom ou pseudo du demandeur"
-#: models.py:367
+#: models.py:368
msgid "Submitter email"
msgstr "Courriel du demandeur"
-#: models.py:369
+#: models.py:370
msgid "Submitter comment"
msgstr "Commentaire du demandeur"
-#: models.py:371
+#: models.py:372
msgid "Submited"
msgstr "Soumis"
-#: models.py:373
+#: models.py:374
msgid "Modified"
msgstr "Modifié"
-#: models.py:374
+#: models.py:375
msgid "Disabled"
msgstr "Désactivé"
-#: models.py:375
+#: models.py:376
msgid "Imported"
msgstr "Importé"
-#: models.py:376
+#: models.py:377
msgid "Excluded"
msgstr "Exclu"
-#: models.py:378
+#: models.py:379
msgid "Status"
msgstr "État"
-#: models.py:379
+#: models.py:380
msgid "Import key"
msgstr "Clé d'import"
-#: models.py:381
+#: models.py:382
msgid "Import version"
msgstr "Version de l'import"
-#: models.py:385
+#: models.py:384
+msgid "Source"
+msgstr "Source"
+
+#: models.py:386
msgid "Modified since last import"
msgstr "Modifié depuis le dernier import"
-#: models.py:387
+#: models.py:388
msgid "Not to be imported inside OSM"
msgstr "Ne pas importer dans OSM"
@@ -430,7 +538,7 @@ msgstr ""
msgid "Reference marker"
msgstr "Point d'intérêt de référence"
-#: models.py:449 utils.py:464
+#: models.py:449 utils.py:471
msgid "Localisation"
msgstr "Localisation"
@@ -438,160 +546,168 @@ msgstr "Localisation"
msgid "Available Date"
msgstr "Date de mise en disponibilité"
-#: models.py:455 utils.py:463 templates/chimere/edit.html:49
-#: templates/chimere/edit_route.html:46
+#: models.py:455 utils.py:470 templates/admin/chimere/managed_modified.html:31
+#: templates/chimere/edit.html:49 templates/chimere/edit_route.html:46
msgid "Description"
msgstr "Description"
-#: models.py:519 models.py:1462
+#: models.py:523 models.py:1495
msgid "Point of interest"
msgstr "Point d'intérêt"
-#: models.py:687
+#: models.py:691
msgid "Audio"
msgstr "Audio"
-#: models.py:688
+#: models.py:692
msgid "Video"
msgstr "Vidéo"
-#: models.py:690
+#: models.py:694
msgid "Other"
msgstr "Autre"
-#: models.py:691
+#: models.py:695
msgid "Media type"
msgstr "Type de media"
-#: models.py:694
+#: models.py:698
msgid "Mime type"
msgstr "Type mime"
-#: models.py:696
+#: models.py:700
msgid "Inside an iframe"
msgstr "À l'intérieur d'un iframe"
-#: models.py:700
+#: models.py:704
msgid "Multimedia type"
msgstr "Type de multimedia"
-#: models.py:701
+#: models.py:705
msgid "Multimedia types"
msgstr "Types de multimedia"
-#: models.py:736
+#: models.py:714
+msgid "Automatic recognition"
+msgstr "Reconnaissance automatique"
+
+#: models.py:740
msgid "Extension name"
msgstr "Nom de l'extension"
-#: models.py:738
+#: models.py:742
msgid "Associated multimedia type"
msgstr "Type de multimedia associé"
-#: models.py:742
+#: models.py:746
msgid "Multimedia extension"
msgstr "Extension de fichier multimedia"
-#: models.py:743
+#: models.py:747
msgid "Multimedia extensions"
msgstr "Extensions de fichier multimedia"
-#: models.py:753 models.py:797
+#: models.py:757 models.py:817
msgid "Display inside the description?"
msgstr "Apparaît dans la description ?"
-#: models.py:758
+#: models.py:762
msgid "Multimedia file"
msgstr "Fichier multimedia"
-#: models.py:799
+#: models.py:819
msgid "Thumbnail"
msgstr "Miniature"
-#: models.py:803
+#: models.py:823
msgid "Thumbnail height"
msgstr "Hauteur de la miniature"
-#: models.py:805
+#: models.py:825
msgid "Thumbnail width"
msgstr "Largeur de la miniature"
-#: models.py:814
+#: models.py:834
msgid "Picture file"
msgstr "Fichier d'image"
-#: models.py:909
+#: models.py:929
msgid "Raw file (gpx or kml)"
msgstr "Fichier brut (gpx ou kml)"
-#: models.py:911
+#: models.py:931
msgid "Simplified file"
msgstr "Fichier simplifié"
-#: models.py:913
+#: models.py:933
msgid "KML"
msgstr "KML"
-#: models.py:913
+#: models.py:933
msgid "GPX"
msgstr "GPX"
-#: models.py:918
+#: models.py:938
msgid "Route file"
msgstr "Fichier de trajet"
-#: models.py:919
+#: models.py:939
msgid "Route files"
msgstr "Fichiers de trajet"
-#: models.py:969
+#: models.py:989
msgid "Reference route"
msgstr "Trajet de référence"
-#: models.py:973
+#: models.py:993
msgid "Associated file"
msgstr "Fichier associé"
-#: models.py:1225
+#: models.py:998
+msgid "Has an associated marker"
+msgstr "Dispose d'un marqueur associé"
+
+#: models.py:1258
msgid "Layer code"
msgstr "Code pour la couche"
-#: models.py:1231
+#: models.py:1264
msgid "Layer"
msgstr "Couche"
-#: models.py:1237
+#: models.py:1270
msgid "Area urn"
msgstr "Urn de la zone"
-#: models.py:1239 templates/chimere/blocks/welcome.html:3
+#: models.py:1272 templates/chimere/blocks/welcome.html:3
msgid "Welcome message"
msgstr "Message d'accueil"
-#: models.py:1243
+#: models.py:1276
msgid "Upper left corner"
msgstr "Coin en haut à gauche"
-#: models.py:1245
+#: models.py:1278
msgid "Lower right corner"
msgstr "Coin en bas à droite"
-#: models.py:1247
+#: models.py:1280
msgid "Default area"
msgstr "Zone par défaut"
-#: models.py:1248
+#: models.py:1281
msgid "Only one area is set by default"
msgstr "Seule une zone est définie par défaut"
-#: models.py:1252
+#: models.py:1285
msgid "Sub-categories checked by default"
msgstr "Sous-catégories cochées par défaut"
-#: models.py:1254
+#: models.py:1287
msgid "Sub-categories dynamicaly displayed"
msgstr "Sous-categories affichées dynamiquement"
-#: models.py:1255
+#: models.py:1288
msgid ""
"If checked, categories are only displayed in the menu if they are available "
"on the current extent."
@@ -599,76 +715,72 @@ msgstr ""
"Si coché, les catégories sont disponibles sur le menu seulement si elles "
"apparaissent sur la zone affichée."
-#: models.py:1259 models.py:1414
+#: models.py:1292 models.py:1447
msgid "Restricted to theses sub-categories"
msgstr "Restreindre à ces sous-categories"
-#: models.py:1260
+#: models.py:1293
msgid "If no sub-category is set all sub-categories are available"
msgstr ""
"Si aucune sous-catégorie n'est définie toutes les sous-catégories sont "
"disponibles"
-#: models.py:1262
+#: models.py:1295
msgid "Link to an external CSS"
msgstr "Lien vers une feuille de style externe"
-#: models.py:1264
+#: models.py:1297
msgid "Restrict to the area extent"
msgstr "Restreindre à l'étendue de la zone"
-#: models.py:1399 widgets.py:86
+#: models.py:1432 widgets.py:88
msgid "Default layer"
msgstr "Couche par défaut"
-#: models.py:1403 models.py:1404
+#: models.py:1436 models.py:1437
msgid "Layers"
msgstr "Couches"
-#: models.py:1412
+#: models.py:1445
msgid "Mandatory"
msgstr "Obligatoire"
-#: models.py:1415
+#: models.py:1448
msgid ""
"If no sub-category is set all the property applies to all sub-categories"
msgstr ""
"Si aucune sous-catégorie n'est précisée, cette propriété est disponible pour "
"toutes les sous-catégories"
-#: models.py:1417
+#: models.py:1450
msgid "Text"
msgstr "Texte"
-#: models.py:1418
+#: models.py:1451
msgid "Long text"
msgstr "Texte long"
-#: models.py:1419
-msgid "Password"
-msgstr "Mot de passe"
-
-#: models.py:1421
+#: models.py:1454
msgid "Choices"
msgstr "Choix"
-#: models.py:1429
+#: models.py:1462
msgid "Type"
msgstr "Type"
-#: models.py:1434 models.py:1450 models.py:1464
+#: models.py:1467 models.py:1483 models.py:1497
msgid "Property model"
msgstr "Modèle de propriété"
-#: models.py:1451 models.py:1465
+#: models.py:1484 models.py:1498
msgid "Value"
msgstr "Valeur"
-#: models.py:1457
+#: models.py:1490
msgid "Model property choice"
msgstr "Choix pour les modèles de propriété"
-#: models.py:1476
+#: models.py:1509
msgid "Property"
msgstr "Propriété"
@@ -722,63 +834,69 @@ msgstr "Export échoué"
msgid "Export canceled"
msgstr "Export annulé"
-#: utils.py:127 utils.py:176
+#: utils.py:130 utils.py:179
msgid "Bad zip file"
msgstr "Mauvais fichier zip"
-#: utils.py:179
+#: utils.py:182
msgid "Missing file(s) inside the zip file"
msgstr "Fichier(s) manquant(s) dans l'archive zip"
-#: utils.py:220
+#: utils.py:223
msgid "Bad XML file"
msgstr "Mauvais fichier XML"
-#: utils.py:305
+#: utils.py:308
msgid "Error while reading the data source."
msgstr "Erreur lors de la lecture de la source."
-#: utils.py:340
+#: utils.py:326
+#, python-format
+msgid "SRID cannot be guessed. The default SRID (%s) has been used."
+msgstr "Le SRID n'a pu être trouvé. Le SRID par défaut (%s) a été utilisé."
+
+#: utils.py:347
msgid "Type of geographic item of this shapefile is not managed by Chimère."
msgstr ""
"Les types des éléments géographiques de ce fichier Shapefile ne sont pas "
"gérés par Chimère."
-#: utils.py:360
+#: utils.py:367
msgid "Bad Shapefile"
msgstr "Mauvais fichier Shapefile"
-#: utils.py:402
+#: utils.py:409
msgid "Could not create file!"
msgstr "Ne peut pas créer le fichier !"
-#: utils.py:413
+#: utils.py:420
msgid "Failed to create field"
msgstr "Ne peut pas créer un champ"
-#: utils.py:459 templates/chimere/edit.html:44
-#: templates/chimere/edit_route.html:41 templates/chimere/main_map.html:13
+#: utils.py:466 templates/admin/chimere/managed_modified.html:25
+#: templates/chimere/edit.html:44 templates/chimere/edit_route.html:41
+#: templates/chimere/main_map.html:13
#: templates/chimere/main_map_simple.html:10
msgid "Categories"
msgstr "Catégories"
-#: utils.py:492
+#: utils.py:499
msgid "Invalid CSV format"
msgstr "Fichier CSV non valide"
-#: utils.py:567
+#: utils.py:574
msgid "RSS feed is not well formed"
msgstr "Flux RSS non valide"
-#: utils.py:637
+#: utils.py:649
msgid "Nothing to import"
msgstr "Rien à importer"
-#: utils.py:725
+#: utils.py:737
msgid "New items imported - validate them before exporting"
msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter"
-#: utils.py:727
+#: utils.py:739
msgid ""
"There are items from a former import not yet validated - validate them "
"before exporting"
@@ -786,15 +904,19 @@ msgstr ""
"Il y a des éléments d'un import précédent pas encore validé - Validez les "
"avant d'exporter"
-#: utils.py:737
+#: utils.py:751
+msgid "Bad params - programming error"
+msgstr "Mauvais paramètres - erreur de programmation"
+
+#: utils.py:761
msgid "Bad param"
msgstr "Mauvais paramètre"
-#: utils.py:752
+#: utils.py:776
msgid "No non ambigious tag is defined in the XAPI request"
msgstr "Aucun « tag » non ambigu n'est défini dans la requête XAPI"
-#: utils.py:754
+#: utils.py:778
msgid ""
"No bounding box is defined in the XAPI request.If you are sure to manage the "
"entire planet set the bounding box to -180,-90,180,90"
@@ -803,19 +925,19 @@ msgstr ""
"vouloir lancer la requête sur la planète entière fixez la « bounding box » "
"à -180,-90,180,90"
-#: views.py:272
+#: views.py:278
msgid "There are missing field(s) and/or errors in the submited form."
msgstr "Il y a des champs manquants ou des erreurs dans ce formulaire."
-#: views.py:357
+#: views.py:363
msgid "Bad file. Please check it with an external software."
msgstr "Fichier incohérent. Merci de le vérifier avec un logiciel externe."
-#: views.py:469
+#: views.py:475
msgid "Comments/request on the map"
msgstr "Commentaires/requètes sur la carte"
-#: views.py:472
+#: views.py:478
msgid ""
"Thank you for your contribution. It will be taken into account. If you have "
"left your email you may be contacted soon for more details."
@@ -824,56 +946,56 @@ msgstr ""
"laissé votre courriel vous serez peut-être contacté bientôt pour plus de "
"détails."
-#: views.py:476
+#: views.py:482
msgid "Temporary error. Renew your message later."
msgstr "Erreur temporaire. Réenvoyez votre message plus tard."
-#: views.py:648
+#: views.py:656
msgid "No category available in this area."
msgstr "Pas de catégorie disponible sur cette zone."
-#: views.py:748
+#: views.py:756
msgid "Bad geometry"
msgstr "Géométrie incorrecte"
-#: views.py:824
+#: views.py:841
msgid "Incorrect choice in the list"
msgstr "Choix incorrect dans la liste"
-#: widgets.py:233
+#: widgets.py:242
msgid "Street, City, Country"
msgstr "Rue, Commune, Pays"
-#: widgets.py:300
+#: widgets.py:311
msgid "Latitude"
msgstr "Latitude"
-#: widgets.py:300
+#: widgets.py:311
msgid "Longitude"
msgstr "Longitude"
-#: widgets.py:325
+#: widgets.py:335
msgid "Invalid point"
msgstr "Point invalide"
-#: widgets.py:378
+#: widgets.py:391
msgid "Creation mode"
msgstr "Mode création"
-#: widgets.py:379
+#: widgets.py:392
msgid "To start drawing the route click on the toggle button: \"Draw\"."
msgstr ""
"Pour commencer le dessin cliquez sur le bouton&nbsp;: «&nbsp;Tracer&nbsp;»."
-#: widgets.py:381
+#: widgets.py:394
msgid "Then click on the map to begin the drawing."
msgstr "Puis cliquez sur la carte pour commencer le dessin."
-#: widgets.py:382
+#: widgets.py:395
msgid "You can add points by clicking again."
msgstr "Vous pouvez ajouter des points en cliquant de nouveau."
-#: widgets.py:383
+#: widgets.py:396
msgid ""
"To finish the drawing double click. When the drawing is finished you can "
"edit it."
@@ -881,7 +1003,7 @@ msgstr ""
"Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez "
"toujours l'éditer."
-#: widgets.py:385
+#: widgets.py:398
msgid ""
"While creating to undo a drawing click again on the toggle button \"Stop "
"drawing\"."
@@ -889,17 +1011,17 @@ msgstr ""
"En mode création vous pouvez annuler un tracé en appuyant sur le bouton "
"«&nbsp;Arrêter le tracé&nbsp;»."
-#: widgets.py:390
+#: widgets.py:403
msgid "Modification mode"
msgstr "Mode modification"
-#: widgets.py:391
+#: widgets.py:404
msgid "To move a point click on it and drag it to the desired position."
msgstr ""
"Pour bouger un point, cliquez dessus, maintenez le click pour le déposer à "
"la position désirée."
-#: widgets.py:392
+#: widgets.py:405
msgid ""
"To delete a point move the mouse cursor over it and press the \"d\" or \"Del"
"\" key."
@@ -907,7 +1029,7 @@ msgstr ""
"Pour supprimer un point, mettez le curseur de la souris sur celui-ci et "
"appuyez sur le touche «&nbsp;d&nbsp;» ou «&nbsp;Suppr&nbsp;»."
-#: widgets.py:394
+#: widgets.py:407
msgid ""
"To add a point click in the middle of a segment and drag the new point to "
"the desired position"
@@ -916,39 +1038,93 @@ msgstr ""
"maintenez le bouton appuyé et déplacez le nouveau point à la position "
"désirée."
-#: widgets.py:401
+#: widgets.py:414
msgid "Give a name and set category before uploading a file."
msgstr ""
"Renseignez le nom et choisissez au moins une catégorie avant de déposer un "
"fichier."
-#: widgets.py:404
+#: widgets.py:417
msgid "Upload a route file (GPX or KML)"
msgstr "Déposer un trajet (fichier GPX ou KML)"
-#: widgets.py:405
+#: widgets.py:418
msgid "or"
msgstr "ou"
-#: widgets.py:410
+#: widgets.py:423
msgid "Start \"hand\" drawing"
msgstr "Commencer le tracé manuellement"
-#: widgets.py:433
+#: widgets.py:446
msgid "Move on the map"
msgstr "Se déplacer"
-#: widgets.py:433
+#: widgets.py:446
msgid "Draw"
msgstr "Tracer"
-#: widgets.py:513
+#: widgets.py:536
msgid "Hold CTRL, click and drag to select area on the map"
msgstr ""
"Maintenir la touche Control, cliquez puis glissez pour sélectionner une zone "
"sur la carte"
-#: widgets.py:579
+#: widgets.py:593
+msgid "Type:"
+msgstr "Type :"
+
+#: widgets.py:593
+msgid "Node"
+msgstr "Nœud"
+
+#: widgets.py:594
+msgid "Way"
+msgstr "Route"
+
+#: widgets.py:605
+msgid ""
+"Enter an OSM \"tag=value\" string such as \"amenity=pub\". A list of common "
+"tag is available <a href='https://wiki.openstreetmap.org/wiki/Map_Features' "
+"target='_blank'>here</a>."
+msgstr ""
+"Entrez une chaîne OSM de type \"clé=valeur\" telle que \"amenity=pub\". Une "
+"liste des clés est disponible <a href='https://wiki.openstreetmap.org/wiki/"
+"FR:Map_Features' target='_blank'>ici</a>."
+
+#: widgets.py:612
+msgid "Tag:"
+msgstr "Clé/valeur :"
+
+#: widgets.py:616
+msgid "You have to select an area."
+msgstr "Vous devez sélectionner une zone."
+
+#: widgets.py:618
+msgid "You have to select a type."
+msgstr "Vous devez sélectionner un type."
+
+#: widgets.py:620
+msgid "You have to insert a filter tag."
+msgstr "Vous devez saisir une clé=valeur."
+
+#: widgets.py:622
+msgid "If you change the above form don't forget to refresh before submit!"
+msgstr ""
+"Si vous modifiez le formulaire ci-dessus n'oubliez pas de rafraîchir avant "
+"de valider !"
+
+#: widgets.py:625
+msgid "You can put a Folder name of the KML file to filter on it."
+msgstr ""
+"Vous pouvez saisir le nom d'un « Folder » du fichier KML pour filter sur "
+"celui-ci."
+
+#: widgets.py:633
+msgid "Refresh"
+msgstr "Rafraîchir"
+
+#: widgets.py:699
msgid "Select..."
msgstr "Sélectionner..."
@@ -964,6 +1140,73 @@ msgstr "Erreur interne du serveur"
msgid "Chimère administration"
msgstr "Administration de Chimère"
+#: templates/admin/chimere/managed_modified.html:11
+msgid ""
+"Be careful: after validation, the modified item will be deleted. There is no "
+"roll-back."
+msgstr ""
+"Attention: après validation, l'élément modifié sera supprimé. Il n'y a pas "
+"d'annulation possible."
+
+#: templates/admin/chimere/managed_modified.html:20
+msgid "Reference"
+msgstr "Référence"
+
+#: templates/admin/chimere/managed_modified.html:20
+msgid "Modified item"
+msgstr "Élément modifié"
+
+#: templates/admin/chimere/managed_modified.html:20
+msgid "Accept modification"
+msgstr "Accepter la modification"
+
+#: templates/admin/chimere/managed_modified.html:30
+msgid "Emplacement"
+msgstr "Emplacement"
+
+#: templates/admin/chimere/managed_modified.html:43
+#: templates/admin/chimere/osm_export.html:27
+msgid "Back to list"
+msgstr "Retourner à la liste"
+
+#: templates/admin/chimere/osm_export.html:21
+msgid "Only points of interest are managed by this export."
+msgstr "Seuls les points d'intérêt sont gérés par cet export."
+
+#: templates/admin/chimere/osm_export.html:23
+msgid ""
+"Before exporting to OSM an import is done to verify that no modification has "
+"been made. All pending imported item have to be validated before export."
+msgstr ""
+"Préalablement à tout export vers OSM, un import est réalisé pour vérifier "
+"qu'aucune modification n'a été faite sur les données nous concernant. Par "
+"ailleurs toutes les données importées doivent être traitées avant l'export."
+
+#: templates/admin/chimere/osm_export.html:25
+msgid ""
+"Ensure that all the data exported to OSM have an appropriate license. You "
+"can exclude some points of interest by checking the checkbox \"Not to be "
+"imported in OSM\" in the point of interest form. <strong>If you are not sure "
+"of what you are doing: DON'T EXPORT TO OSM</strong>!"
+msgstr ""
+"Vérifiez que toutes les données à exporter vers OSM ont une licence "
+"compatible. Vous pouvez exclure certains points d'intérêt en cochant la "
+"case « Ne pas importer dans OSM » sur le formulaire de point d'intérêt. "
+"<strong>Si vous n'êtes pas sûr de ce que vous êtes entrain de faire : "
+"N'IMPORTEZ PAS DANS OSM</strong> !"
+
+#: templates/admin/chimere/osm_export.html:28
+msgid "Export to OSM"
+msgstr "Exporter vers OSM"
+
+#: templates/admin/chimere/propertymodel/change_form.html:5
+msgid ""
+"After add/modification of property models you'll have to reload the "
+"webserver."
+msgstr ""
+"Après ajout/modification de modèle de propriété vous aurez à recharger le "
+"serveur web."
+
#: templates/chimere/base.html:12
msgid "You must enable JavaScript in your browser to display Chimère."
msgstr ""
@@ -996,11 +1239,15 @@ msgstr "Licence :"
msgid "Show multimedia gallery"
msgstr "Montrer la galerie multimedia"
-#: templates/chimere/detail.html:32 templates/chimere/detail.html.py:33
+#: templates/chimere/detail.html:32
+msgid "Submit an amendment"
+msgstr "Proposer une modification"
+
+#: templates/chimere/detail.html:35 templates/chimere/detail.html.py:36
msgid "Propose amendment"
msgstr "Proposer une modification"
-#: templates/chimere/detail.html:32
+#: templates/chimere/detail.html:35
msgid "I would like to propose an amendment for this item:"
msgstr "Je souhaiterai proposer une modification pour cet élément :"
@@ -1061,6 +1308,10 @@ msgstr "Proposez"
msgid "Add/modify a route"
msgstr "Ajout ou modifier un trajet"
+#: templates/chimere/main_map.html:35
+msgid "Simple map"
+msgstr "Carte simple"
+
#: templates/chimere/upload_file.html:13
msgid "Thank you for your submission!"
msgstr "Merci pour votre proposition !"
@@ -1075,6 +1326,7 @@ msgstr "Déposer"
#: templates/chimere/blocks/alternate_multimedia.html:33
#: templates/chimere/blocks/alternate_multimedia.html:51
+#: templates/chimere/blocks/inline_formset.html:22
msgid "Add"
msgstr "Ajouter"
@@ -1088,6 +1340,9 @@ msgid ""
"ipsum. Donec vel urna a turpis consectetur consectetur. Vestibulum ut enim "
"vel odio porta vulputate."
msgstr ""
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu luctus "
+"ipsum. Donec vel urna a turpis consectetur consectetur. Vestibulum ut enim "
+"vel odio porta vulputate."
#: templates/chimere/blocks/alternate_multimedia.html:44
msgid "Audio, video, other..."
@@ -1101,10 +1356,6 @@ msgstr "Téléchargement"
msgid "Or"
msgstr "Ou"
-#: templates/chimere/blocks/alternate_multimedia.html:49
-msgid "Web address"
-msgstr "Adresse web"
-
#: templates/chimere/blocks/alternate_multimedia.html:80
msgid "You must provide a name."
msgstr "Vous devez donner un nom."
@@ -1139,7 +1390,7 @@ msgstr "Zoomer sur"
msgid "Tell me more..."
msgstr "En savoir plus..."
-#: templates/chimere/blocks/categories.html:27
+#: templates/chimere/blocks/categories.html:28
msgid "Display markers and routes waiting for validation"
msgstr ""
"Afficher les points remarquables et les trajets en attente de validation"
@@ -1239,7 +1490,7 @@ msgstr "Départ :"
msgid "Finish:"
msgstr "Arrivée :"
-#: templates/chimere/blocks/routing.html:43
+#: templates/chimere/blocks/routing.html:44
msgid "Step"
msgstr "Étape"
@@ -1319,7 +1570,7 @@ msgstr "Description :"
msgid ":"
msgstr " :"
-#: templatetags/chimere_tags.py:79
+#: templatetags/chimere_tags.py:80
#, python-format
msgid "Welcome to the %s"
msgstr "Bienvenue sur %s"
diff --git a/chimere/migrations/0048_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py b/chimere/migrations/0038_osm_import_filtr.py
index 4b40fb9..2b8666b 100644
--- a/chimere/migrations/0048_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py
+++ b/chimere/migrations/0038_osm_import_filtr.py
@@ -1,37 +1,24 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
-from south.v2 import SchemaMigration
+from south.v2 import DataMigration
from django.db import models
-
-class Migration(SchemaMigration):
+class Migration(DataMigration):
def forwards(self, orm):
- # Adding unique constraint on 'Area', fields ['order']
- db.create_unique('chimere_area', ['order'])
-
- # Adding field 'Importer.associate_marker_to_way'
- db.add_column('chimere_importer', 'associate_marker_to_way',
- self.gf('django.db.models.fields.BooleanField')(default=True),
- keep_default=False)
-
- # Adding field 'Route.has_associated_marker'
- db.add_column('chimere_route', 'has_associated_marker',
- self.gf('django.db.models.fields.BooleanField')(default=True),
- keep_default=False)
-
+ for importer in orm['chimere.Importer'].objects.filter(
+ importer_type='OSM').all():
+ if importer.filtr:
+ continue
+ splited_url = importer.source.split('/')
+ importer.filtr = splited_url[-1]
+ importer.source = "/".join(splited_url[:-1])+"/"
+ importer.save()
def backwards(self, orm):
- # Removing unique constraint on 'Area', fields ['order']
- db.delete_unique('chimere_area', ['order'])
-
- # Deleting field 'Importer.associate_marker_to_way'
- db.delete_column('chimere_importer', 'associate_marker_to_way')
-
- # Deleting field 'Route.has_associated_marker'
- db.delete_column('chimere_route', 'has_associated_marker')
-
+ # no backward necessary
+ pass
models = {
'chimere.area': {
@@ -90,7 +77,7 @@ class Migration(SchemaMigration):
},
'chimere.importer': {
'Meta': {'object_name': 'Importer'},
- 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
@@ -248,4 +235,5 @@ class Migration(SchemaMigration):
}
}
- complete_apps = ['chimere'] \ No newline at end of file
+ complete_apps = ['chimere']
+ symmetrical = True
diff --git a/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py b/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py
new file mode 100644
index 0000000..0b26a27
--- /dev/null
+++ b/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py
@@ -0,0 +1,252 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'MultimediaExtension'
+ db.create_table('chimere_multimediaextension', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=6)),
+ ('multimedia_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='extensions', to=orm['chimere.MultimediaType'])),
+ ))
+ db.send_create_signal('chimere', ['MultimediaExtension'])
+
+
+ # Changing field 'MultimediaFile.multimedia_type'
+ db.alter_column('chimere_multimediafile', 'multimedia_type_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.MultimediaType'], null=True))
+
+ def backwards(self, orm):
+ # Deleting model 'MultimediaExtension'
+ db.delete_table('chimere_multimediaextension')
+
+
+ # User chose to not deal with backwards NULL issues for 'MultimediaFile.multimedia_type'
+ raise RuntimeError("Cannot reverse this migration. 'MultimediaFile.multimedia_type' and its values cannot be restored.")
+
+ models = {
+ 'chimere.area': {
+ 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}),
+ 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
+ 'restrict_to_extent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'db_table': "'chimere_subcategory_areas'", 'to': "orm['chimere.SubCategory']"}),
+ 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}),
+ 'urn': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'blank': 'True'}),
+ 'welcome_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'chimere.arealayers': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'AreaLayers'},
+ 'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Area']"}),
+ 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Layer']"}),
+ 'order': ('django.db.models.fields.IntegerField', [], {})
+ },
+ 'chimere.category': {
+ 'Meta': {'ordering': "['order']", 'object_name': 'Category'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {})
+ },
+ 'chimere.color': {
+ 'Meta': {'ordering': "['order']", 'object_name': 'Color'},
+ 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
+ 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {})
+ },
+ 'chimere.colortheme': {
+ 'Meta': {'object_name': 'ColorTheme'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'})
+ },
+ 'chimere.icon': {
+ 'Meta': {'object_name': 'Icon'},
+ 'height': ('django.db.models.fields.IntegerField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {})
+ },
+ 'chimere.importer': {
+ 'Meta': {'object_name': 'Importer'},
+ 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'source_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'chimere.layer': {
+ 'Meta': {'object_name': 'Layer'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'})
+ },
+ 'chimere.marker': {
+ 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'},
+ 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'point': ('chimere.widgets.PointField', [], {}),
+ 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}),
+ 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}),
+ 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'})
+ },
+ 'chimere.multimediaextension': {
+ 'Meta': {'object_name': 'MultimediaExtension'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'multimedia_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extensions'", 'to': "orm['chimere.MultimediaType']"}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+ },
+ 'chimere.multimediafile': {
+ 'Meta': {'object_name': 'MultimediaFile'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'marker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'multimedia_files'", 'to': "orm['chimere.Marker']"}),
+ 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'multimedia_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.MultimediaType']", 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
+ },
+ 'chimere.multimediatype': {
+ 'Meta': {'object_name': 'MultimediaType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'})
+ },
+ 'chimere.news': {
+ 'Meta': {'object_name': 'News'},
+ 'areas': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'to': "orm['chimere.Area']", 'null': 'True', 'blank': 'True'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'})
+ },
+ 'chimere.picturefile': {
+ 'Meta': {'object_name': 'PictureFile'},
+ 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'marker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pictures'", 'to': "orm['chimere.Marker']"}),
+ 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+ 'thumbnailfile': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'chimere.property': {
+ 'Meta': {'object_name': 'Property'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'marker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Marker']"}),
+ 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.PropertyModel']"}),
+ 'value': ('django.db.models.fields.TextField', [], {})
+ },
+ 'chimere.propertymodel': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'PropertyModel'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mandatory': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {}),
+ 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'properties'", 'blank': 'True', 'to': "orm['chimere.SubCategory']"}),
+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '1'})
+ },
+ 'chimere.route': {
+ 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Route'},
+ 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.RouteFile']", 'null': 'True', 'blank': 'True'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'has_associated_marker': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}),
+ 'route': ('chimere.widgets.RouteField', [], {}),
+ 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'chimere.routefile': {
+ 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'},
+ 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'})
+ },
+ 'chimere.subcategory': {
+ 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subcategories'", 'to': "orm['chimere.Category']"}),
+ 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}),
+ 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}),
+ 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ 'chimere.tinyurl': {
+ 'Meta': {'object_name': 'TinyUrl'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'})
+ }
+ }
+
+ complete_apps = ['chimere'] \ No newline at end of file
diff --git a/chimere/models.py b/chimere/models.py
index 183e22d..9113cfe 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -319,13 +319,12 @@ class Importer(models.Model):
'''
importer_type = models.CharField(_(u"Importer type"), max_length=4,
choices=IMPORTER_CHOICES)
- # URL of a KML file or a XAPI service for OSM
- source = models.CharField(_(u"Source"), max_length=200,
+ filtr = models.CharField(_(u"Filter"), max_length=200,
+ blank=True, null=True)
+ source = models.CharField(_(u"Web address"), max_length=200,
blank=True, null=True)
source_file = models.FileField(_(u"Source file"),
upload_to='import_files', blank=True, null=True)
- filtr = models.CharField(_(u"Filter"), max_length=200,
- blank=True, null=True)
default_name = models.CharField(_(u"Name by default"), max_length=200,
blank=True, null=True)
srid = models.IntegerField(_(u"SRID"), blank=True, null=True)
@@ -385,20 +384,19 @@ class GeographicItem(models.Model):
import_source = models.CharField(_(u"Source"), max_length=200,
blank=True, null=True)
modified_since_import = models.BooleanField(_(u"Modified since last import"),
- default=False)
+ default=True)
not_for_osm = models.BooleanField(_(u"Not to be imported inside OSM"),
default=False)
origin = models.CharField(_(u"Origin"), max_length=100,
blank=True, null=True)
license = models.CharField(_(u"License"), max_length=100,
blank=True, null=True)
- if settings.CHIMERE_DAYS_BEFORE_EVENT:
- start_date = models.DateField(_(u"Start date"), blank=True, null=True,
- help_text=_(u"Not mandatory. Set it for dated item such as event. "\
- u"Format YYYY-MM-DD"))
- end_date = models.DateField(_(u"End date"), blank=True, null=True,
- help_text=_(u"Not mandatory. Set it only if you have a multi-day "\
- u"event. Format YYYY-MM-DD"))
+ start_date = models.DateField(_(u"Start date"), blank=True, null=True,
+ help_text=_(u"Not mandatory. Set it for dated item such as event. "\
+ u"Format YYYY-MM-DD"))
+ end_date = models.DateField(_(u"End date"), blank=True, null=True,
+ help_text=_(u"Not mandatory. Set it only if you have a multi-day "\
+ u"event. Format YYYY-MM-DD"))
class Meta:
abstract = True
@@ -713,7 +711,7 @@ class MultimediaType(models.Model):
def get_tuples(cls):
vals = cls.objects.filter(available=True).order_by('media_type',
'name')
- tuples, c_tpe = [('', '--')], None
+ tuples, c_tpe = [('', _("Automatic recognition"))], None
media_type_dct = dict(cls.MEDIA_TYPES)
for tpe, pk, name in [(media_type_dct[v.media_type], v.pk, v.name)
for v in vals]:
@@ -755,7 +753,7 @@ class MultimediaFile(models.Model):
name = models.CharField(_(u"Name"), max_length=150)
url = models.URLField(_(u"Url"), max_length=200)
order = models.IntegerField(_(u"Order"), default=1)
- multimedia_type = models.ForeignKey(MultimediaType)
+ multimedia_type = models.ForeignKey(MultimediaType, blank=True, null=True)
miniature = models.BooleanField(_(u"Display inside the description?"),
default=settings.CHIMERE_MINIATURE_BY_DEFAULT)
marker = models.ForeignKey(Marker, related_name='multimedia_files')
@@ -767,24 +765,40 @@ class MultimediaFile(models.Model):
def __unicode__(self):
return self.name or u""
- def save(self, *args, **kwargs):
- # manage iframe of video providers
- if self.multimedia_type.name.lower() in IFRAME_LINKS:
- regexps, lnk = IFRAME_LINKS[self.multimedia_type.name.lower()]
- key = None
- for regexp in regexps:
- key = regexp.findall(self.url)
- if key:
- key = key[0]
- break
- if key:
- self.url = lnk % key
- super(MultimediaFile, self).save(*args, **kwargs)
-
def multimediafile_post_save(sender, **kwargs):
if not kwargs['instance'] or not kwargs['created']:
return
multimediafile = kwargs['instance']
+ # auto recognition of file types
+ if not multimediafile.multimedia_type:
+ url = multimediafile.url
+ for mm_type in IFRAME_LINKS:
+ res, embeded_url = IFRAME_LINKS[mm_type]
+ if [r for r in res if r.search(url)]:
+ multimedia_type = MultimediaType.objects.get(
+ name__iexact=mm_type)
+ multimediafile.multimedia_type = multimedia_type
+ if not multimediafile.multimedia_type:
+ ext = url.split(".")[-1]
+ q = MultimediaExtension.objects.filter(name__iendswith=ext)
+ if q.count():
+ multimediafile.multimedia_type = q.all()[0].multimedia_type
+ else:
+ # default to an iframe
+ multimediafile.multimedia_type = \
+ MultimediaType.objects.filter(name__iexact='iframe').all()[0]
+ # manage iframe of video providers
+ if multimediafile.multimedia_type.name.lower() in IFRAME_LINKS:
+ regexps, lnk = IFRAME_LINKS[multimediafile.multimedia_type.name.lower()]
+ key = None
+ for regexp in regexps:
+ key = regexp.findall(multimediafile.url)
+ if key:
+ key = key[0]
+ break
+ if key:
+ multimediafile.url = lnk % key
+
mfs = MultimediaFile.objects.filter(marker=multimediafile.marker).exclude(
pk=multimediafile.pk).order_by('order')
for idx, mf in enumerate(mfs.all()):
@@ -1093,7 +1107,7 @@ def route_post_save(sender, **kwargs):
marker_fields = [f.attname for f in Marker._meta.fields]
route_fields = [f.attname for f in Route._meta.fields]
marker_dct = dict([(k, getattr(instance, k)) for k in marker_fields
- if k in route_fields and k not in ('id', 'ref_item_id')])
+ if k in route_fields and k not in ('id', 'ref_item_id')])
marker_dct['point'] = "SRID=%d;POINT(%f %f)" % (instance.route.srid,
instance.route[0][0], instance.route[0][1])
marker, created = Marker.objects.get_or_create(route=instance,
@@ -1233,7 +1247,10 @@ class SimpleArea:
inner join chimere_route_categories rc on rc.subcategory_id=subcat.id and
rc.route_id=rt.id'''
sql += where
- subcats.union(SubCategory.objects.raw(sql))
+ # subcats.union(set(SubCategory.objects.raw(sql)))
+ # set union behave strangely. Doing it manualy...
+ for c in set(SubCategory.objects.raw(sql)):
+ subcats.add(c)
return subcats
class Layer(models.Model):
diff --git a/chimere/static/chimere/css/forms.css b/chimere/static/chimere/css/forms.css
index 46acdb9..a763a34 100644
--- a/chimere/static/chimere/css/forms.css
+++ b/chimere/static/chimere/css/forms.css
@@ -39,9 +39,12 @@ div.bottomform{
margin:0;
border: 1px solid black;
width:100%;
- height:500px;
+ height:350px;
}
+#map_edit #OpenLayers_Control_MaximizeDiv{
+ display:none;
+}
.map_button{
position:absolute;
@@ -129,3 +132,42 @@ div.bottomform{
overflow:hidden;
height:16px;
}
+
+.form-row.field-route,
+.form-row.field-point,
+.form-row.field-filtr.field-map{
+ float:right;
+ width:50%;
+}
+
+.form-row.field-route .help-route{
+ width:150px;
+}
+
+#id_filtr{
+ width:400px;
+}
+
+.aligned .form-row.field-route label,
+.aligned .form-row.field-point label,
+.aligned .input-osm label{
+ display:inline;
+ float:none;
+}
+
+form .aligned .form-row.field-marker p,
+form .aligned .form-row.field-route p,
+form .aligned .input-osm p{
+ padding:0.2em;
+ margin:0;
+}
+
+form .aligned p.help-osm{
+ padding-left:0;
+ margin-left:0;
+}
+
+form .aligned p.help-osm.errornote{
+ padding-left:30px;
+ margin-left:0;
+}
diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css
index caee1a6..67a28a4 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -728,6 +728,10 @@ a#routing_button,
margin:0.3em;
padding:0.2em;
width:100%;
+}
+
+a#welcome_button,
+#permalink{
font-size:14px;
text-align:center;
text-decoration:none;
diff --git a/chimere/static/chimere/js/importer_interface.js b/chimere/static/chimere/js/importer_interface.js
new file mode 100644
index 0000000..9dc669f
--- /dev/null
+++ b/chimere/static/chimere/js/importer_interface.js
@@ -0,0 +1,81 @@
+django.jQuery(function($) {
+ var importer_form_filter = {
+ OSM:new Array('field-filtr', 'field-default_name', 'field-categories',
+ 'field-source'),
+ KML:new Array('field-source', 'field-source_file', 'field-default_name',
+ 'field-filtr', 'field-zipped', 'field-origin',
+ 'field-license', 'field-categories'),
+ SHP:new Array('field-source', 'field-source_file', 'field-default_name',
+ 'field-zipped', 'field-origin', 'field-srid',
+ 'field-license', 'field-categories'),
+ RSS:new Array('field-source', 'field-default_name', 'field-origin',
+ 'field-srid', 'field-license', 'field-categories'),
+ CSV:new Array('field-source', 'field-source_file', 'field-default_name',
+ 'field-origin', 'field-srid', 'field-license',
+ 'field-categories')
+ }
+ var map_initialized;
+ function refresh_importer_form(){
+ $('.form-row').not('.field-importer_type').hide();
+ var importer_val = $('.field-importer_type select').val();
+ if (!importer_val) return;
+ var form_filters = importer_form_filter[importer_val];
+ for (k=0; k<form_filters.length;k++){
+ $('.form-row.'+form_filters[k]).show();
+ }
+ if (importer_val == 'KML'){
+ $('.help-kml').show();
+ } else {
+ $('.help-kml').hide();
+ }
+ if (importer_val == 'OSM'){
+ $('.form-row.field-filtr').addClass('field-map');
+ $('#map_edit').show();
+ if(!$('#id_source').val()){
+ $('#id_source').val(default_xapi);
+ }
+ $('#id_filtr').attr('readonly', true);
+ $('.help-osm').show();
+ $('.input-osm').show();
+ if (!map_initialized){
+ init_map_form();
+ map_initialized = true;
+ }
+ } else {
+ $('.form-row.field-filtr').removeClass('field-map');
+ $('#id_filtr').attr('readonly', false);
+ $('#map_edit').hide();
+ $('.help-osm').hide();
+ $('.input-osm').hide();
+ if($('#id_source').val() == default_xapi) $('#id_source').val('');
+ }
+ }
+ refresh_importer_form();
+ $('.field-importer_type select').change(refresh_importer_form);
+ function refresh_filtr_form(){
+ if (!$('#upper_left_lat').val() ||
+ !parseFloat($('#upper_left_lat').val())){
+ alert(msg_missing_area);
+ return false;
+ }
+ if (!$('input[name=id_filtr_type]:checked').val()){
+ alert(msg_missing_type);
+ return false;
+ }
+ if (!$('#id_filtr_tag').val()){
+ alert(msg_missing_filtr);
+ return false;
+ }
+ value = $('input[name=id_filtr_type]:checked').val();
+ value += '[' + $("#id_filtr_tag").val() + ']';
+ value += '[bbox=';
+ value += $('#upper_left_lon').val() + ',';
+ value += $('#lower_right_lat').val() + ',';
+ value += $('#lower_right_lon').val() + ',';
+ value += $('#upper_left_lat').val();
+ value += ']';
+ $('#id_filtr').val(value);
+ return false;
+ }
+ $('#id_refresh_filtr').click(refresh_filtr_form);
+});
diff --git a/chimere/tasks.py b/chimere/tasks.py
index 43b219d..02e32a4 100644
--- a/chimere/tasks.py
+++ b/chimere/tasks.py
@@ -87,20 +87,18 @@ def importing(importer_pk):
importer.state = unicode(IMPORT_MESSAGES['import_process'][0])
importer.save()
new_item, updated_item, error = importer.manager.get()
- if error:
- importer.state = unicode(IMPORT_MESSAGES['import_failed'][0]) \
- + u" - " + unicode(IMPORT_MESSAGES['import_failed'][1]) % error
- importer.save()
- return
- importer.state = unicode(IMPORT_MESSAGES['import_done'][0]) + u" - " \
+ importer.state = error + ' ' if error else ''
+ importer.state += unicode(IMPORT_MESSAGES['import_done'][0])
+ importer.state += u" - " \
+ unicode(IMPORT_MESSAGES['import_done'][1]) % {'new':new_item,
'updated':updated_item}
+ importer.state = importer.state[:200]
importer.save()
return True
@task()
@single_instance_task(60*10)
-def exporting(importer_pk):
+def exporting(importer_pk, extra_args=[]):
try:
importer = Importer.objects.get(pk=importer_pk)
except ObjectDoesNotExist:
@@ -113,7 +111,7 @@ def exporting(importer_pk):
importer.save()
error = None
try:
- updated_item, error = importer.manager.put()
+ updated_item, error = importer.manager.put(extra_args)
except OsmApi.ApiError, error:
pass
if error:
diff --git a/chimere/templates/admin/managed_modified.html b/chimere/templates/admin/chimere/managed_modified.html
index c55650d..c55650d 100644
--- a/chimere/templates/admin/managed_modified.html
+++ b/chimere/templates/admin/chimere/managed_modified.html
diff --git a/chimere/templates/admin/chimere/osm_export.html b/chimere/templates/admin/chimere/osm_export.html
new file mode 100644
index 0000000..dab123e
--- /dev/null
+++ b/chimere/templates/admin/chimere/osm_export.html
@@ -0,0 +1,31 @@
+{% extends "admin/base_site.html" %}
+{% load chimere_tags i18n admin_static %}
+
+{% block extrahead %}
+<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
+{% endblock %}
+
+
+{% block content %}
+<fieldset class='module'>
+<form method='POST' action='.'>
+{% csrf_token %}
+<input type='hidden' name='action' value='export_to_osm'/>
+<input type='hidden' name='validate' value='1'/>
+<input type='hidden' name='_selected_action' value='{{item.pk}}'/>
+<table>
+{{ form.as_table }}
+</table>
+</fieldset>
+<ul class='messagelist'>
+ <li>{% trans "Only points of interest are managed by this export." %}</li>
+ <li>{{msg_item}}</li>
+ <li>{% trans "Before exporting to OSM an import is done to verify that no modification has been made. All pending imported item have to be validated before export." %}</li>
+</ul>
+<p class='errornote'>{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. <strong>If you are not sure of what you are doing: DON'T EXPORT TO OSM</strong>!{% endblocktrans %}</p>
+<div class='submit-row'>
+<p class='deletelink-box'><a href="{% if item.point %}{% url admin:chimere_marker_changelist %}{%else%}{% url admin:chimere_route_changelist %}{%endif%}">{% trans "Back to list" %}</a></p>
+<input class='default' type='submit' value='{% trans "Export to OSM" %}'/>
+</div>
+</form>
+{% endblock %}
diff --git a/chimere/templates/admin/chimere/propertymodel/change_form.html b/chimere/templates/admin/chimere/propertymodel/change_form.html
new file mode 100644
index 0000000..0ebeab0
--- /dev/null
+++ b/chimere/templates/admin/chimere/propertymodel/change_form.html
@@ -0,0 +1,7 @@
+{% extends "admin/change_form.html" %}
+{% load i18n %}
+{% block after_field_sets %}
+<p class='errornote'>
+{% trans "After add/modification of property models you'll have to reload the webserver." %}
+</p>
+{% endblock %}
diff --git a/chimere/templates/chimere/blocks/alternate_multimedia.html b/chimere/templates/chimere/blocks/alternate_multimedia.html
index 178f68a..50bddd5 100644
--- a/chimere/templates/chimere/blocks/alternate_multimedia.html
+++ b/chimere/templates/chimere/blocks/alternate_multimedia.html
@@ -115,6 +115,7 @@
content += '<input type="hidden" name="'+prefix+'-name" value="'+ $("#multimedia_name").val() +'"/>\n';
content += $("#multimedia_name").val();
content += " <img class='remove-media' alt='Remove media' src='{{STATIC_URL}}chimere/img/close.png'/>";
+ content += " <img class='remove-media' alt='Remove media' src='{{STATIC_URL}}chimere/img/close.png'/>";
content += '</li>';
contener.append(content);
if ($('#media_type_image:checked').val()
diff --git a/chimere/templates/chimere/blocks/categories.html b/chimere/templates/chimere/blocks/categories.html
index 62d909b..d87fe4d 100644
--- a/chimere/templates/chimere/blocks/categories.html
+++ b/chimere/templates/chimere/blocks/categories.html
@@ -1,29 +1,31 @@
{% load i18n %}
- <ul id='ul_categories'>
- {% for category, lst_sub_categories in sub_categories %}
- <li class='main_category'>
- <img class="control_image toggle_category" id="maincategory_img_{{category.id}}" alt="control" src="{{ STATIC_URL }}chimere/img/{% if category.selected %}minus.png{% else %}plus.png{% endif %}" />
- <input type="checkbox" id='checkall_{{category.id}}'>
- {% trans category.name %}
- <img id="zoom_to_category_{{category.id}}" class="zoom_image zoom_to_category" alt='{% trans "Zoom to" %} {{category.name}}' src='{{ STATIC_URL }}chimere/img/zoom.png' />
- <ul class='subcategories' id='maincategory_{{category.id}}'{% if not category.selected %} style='display:None'{% endif %}>
- {% for sub_category in lst_sub_categories %}
- <li id='li_sub_{{sub_category.id}}' class='subcategory'>
- <input type='checkbox' name='category_{{sub_category.id}}' id='category_{{sub_category.id}}'{% if sub_category.selected %} checked='checked'{% endif %}/>
- <label for='category_{{sub_category.id}}'>
- <img alt='{{ sub_category.name }}' src='{{ MEDIA_URL }}{{sub_category.icon.image}}'/>
- {% trans sub_category.name %}
- </label>
- <img id="zoom_to_subcategory_{{sub_category.id}}" class="zoom_image zoom_to_subcategory" alt='{% trans "Zoom to" %} {{sub_category.name}}' src='{{ STATIC_URL }}chimere/img/zoom.png' />
- </li>
- {% endfor %}
- {% if category.description %}
- <li><a href="#" onclick="$('#map').chimere('category_detail', {{category.id}});">{% trans "Tell me more..." %}</a></li>
- {% endif %}
- </ul>
- </li>
- {% endfor %}
- <li id='display_submited'>
- <input type='checkbox' name='display_submited' id='display_submited_check'/> {% trans "Display markers and routes waiting for validation"%}
- </li>
- </ul>
+<ul id='ul_categories'>
+ {% for category, lst_sub_categories in sub_categories %}
+ <li class='main_category'>
+ <img class="control_image toggle_category" id="maincategory_img_{{category.id}}" alt="control" src="{{ STATIC_URL }}chimere/img/{% if category.selected %}minus.png{% else %}plus.png{% endif %}" />
+ <input type="checkbox" id='checkall_{{category.id}}'>
+ {% trans category.name %}
+ <img id="zoom_to_category_{{category.id}}" class="zoom_image zoom_to_category" alt='{% trans "Zoom to" %} {{category.name}}' src='{{ STATIC_URL }}chimere/img/zoom.png' />
+ <ul class='subcategories' id='maincategory_{{category.id}}'{% if not category.selected %} style='display:None'{% endif %}>
+ {% for sub_category in lst_sub_categories %}
+ <li id='li_sub_{{sub_category.id}}' class='subcategory'>
+ <input type='checkbox' name='category_{{sub_category.id}}' id='category_{{sub_category.id}}'{% if sub_category.selected %} checked='checked'{% endif %}/>
+ <label for='category_{{sub_category.id}}'>
+ <img alt='{{ sub_category.name }}' src='{{ MEDIA_URL }}{{sub_category.icon.image}}'/>
+ {% trans sub_category.name %}
+ </label>
+ <img id="zoom_to_subcategory_{{sub_category.id}}" class="zoom_image zoom_to_subcategory" alt='{% trans "Zoom to" %} {{sub_category.name}}' src='{{ STATIC_URL }}chimere/img/zoom.png' />
+ </li>
+ {% endfor %}
+ {% if category.description %}
+ <li><a href="#" onclick="$('#map').chimere('category_detail', {{category.id}});">{% trans "Tell me more..." %}</a></li>
+ {% endif %}
+ </ul>
+ </li>
+ {% endfor %}
+ {% if sub_categories %}
+ <li id='display_submited'>
+ <input type='checkbox' name='display_submited' id='display_submited_check'/> {% trans "Display markers and routes waiting for validation"%}
+ </li>
+ {% endfor %}
+</ul>
diff --git a/chimere/templates/chimere/blocks/inline_formset.html b/chimere/templates/chimere/blocks/inline_formset.html
index 139ad70..61cbd19 100644
--- a/chimere/templates/chimere/blocks/inline_formset.html
+++ b/chimere/templates/chimere/blocks/inline_formset.html
@@ -1,13 +1,13 @@
{% load i18n %}
{% if extra_formset.non_form_errors %}<div class='errors'>{{extra_formset.non_form_errors.as_ul}}</div>{% endif %}
{{ formset.management_form }}
- <table class='inline-table'>
+ <table class='inline-table' id='table_{{formset.prefix}}'>
<caption>{% trans caption %}</caption>
{% for frm in formset%}{%if forloop.first %}
<tr>{% for field in frm%}{% if field.label %}
<th>{{field.label}}</th>{% endif %}{%endfor%}
</tr>{%endif%}
- <tr>{% for field in frm.visible_fields %}
+ <tr id='tr_{{formset.prefix}}_{{forloop.counter0}}'>{% for field in frm.visible_fields %}
<td>{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in frm.hidden_fields %}
@@ -19,3 +19,22 @@
</td>{% endfor %}
</tr>{%endfor%}
</table>
+ <button id='add_new_{{formset.prefix}}'>{% trans "Add" %}</button>
+ <script type='text/javascript'><!--
+ $('#add_new_{{formset.prefix}}').click(function(){
+ var total_input = $("#id_{{formset.prefix}}-TOTAL_FORMS");
+ total_input.val(parseInt(total_input.val())+1);
+ var new_line = $('#tr_{{formset.prefix}}_0').clone();
+ new_line.find('input').val('');
+ new_line.find('input[type=checkbox]').attr('checked', false);
+ new_line.find('select').val('');
+ {% for field in formset.0.visible_fields %}
+ var old_input_id = '{{formset.prefix}}-0-{{field.name}}';
+ var input_id = '{{formset.prefix}}-'+(parseInt(total_input.val())-1)+'-{{field.name}}';
+ new_line.find('#id_'+old_input_id).attr('id', 'id_'+input_id
+ ).attr('name', input_id);
+ {% endfor %}
+ $('#table_{{formset.prefix}}').append(new_line);
+ return false;
+ });
+ // --></script>
diff --git a/chimere/templates/chimere/feeds/rss.html b/chimere/templates/chimere/feeds/rss.html
index 43697ae..53b0a49 100644
--- a/chimere/templates/chimere/feeds/rss.html
+++ b/chimere/templates/chimere/feeds/rss.html
@@ -48,7 +48,7 @@
<h3>{% trans "New points of interest by area" %}</h3>
{% if area_id %}
<div class="fieldWrapper">
- <label for="id_area">{% trans "Choose a pre-defined areas" %}</label>
+ <h4>{% trans "Choose a pre-defined areas" %}</h4>
<select name='id_area' id='id_area' onchange='document.forms["rss_form"].submit();'>
<option value="" selected="selected"> ---- </option>
{% for areaID in area_id %}
@@ -62,7 +62,7 @@
<form method='post' action=''>
{% endif %}
<div class='fieldWrapper'>
-<label>{% trans "Or select the area by zooming and panning this map" %}</label>
+<H4>{% trans "Or select the area by zooming and panning this map" %}</h4>
<div class="map">
{{form.area}}
</div>
diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html
index a2c152d..b7aa868 100644
--- a/chimere/templates/chimere/main_map.html
+++ b/chimere/templates/chimere/main_map.html
@@ -32,6 +32,7 @@
{% display_welcome %}
{% display_news news_visible %}
<div id='permalink' class='ui-widget ui-button ui-state-default ui-corner-all'></div>
+ <a id='simple_button' class='ui-widget ui-button ui-state-default ui-corner-all' href='{% url chimere:simple_index area_name_slash %}'>{% trans "Simple map" %}</a>
</div>
<div id='detail' class='ui-widget ui-corner-all'></div>
{% endblock %}
diff --git a/chimere/tests.py b/chimere/tests.py
index 049fbbe..790eb55 100644
--- a/chimere/tests.py
+++ b/chimere/tests.py
@@ -33,7 +33,11 @@ def areas_setup():
available=True,
upper_left_corner='SRID=4326;POINT(-3 47.5)',
lower_right_corner='SRID=4326;POINT(-2.5 47)')
- return [area_1, area_2]
+ area_3 = Area.objects.create(name='area 3', urn='area-3', order=3,
+ available=True,
+ upper_left_corner='SRID=4326;POINT(-1.5 1.5)',
+ lower_right_corner='SRID=4326;POINT(1.5 -1.5)')
+ return [area_1, area_2, area_3]
def subcategory_setup():
category = Category.objects.create(name='Main category',
@@ -88,6 +92,21 @@ def marker_setup(sub_categories=[]):
markers.append(marker_3)
return markers
+def route_setup(sub_categories=[]):
+ if not sub_categories:
+ sub_categories = subcategory_setup()
+ current_date = datetime.datetime.now()
+ routes = []
+ route_1 = Route.objects.create(name="Route 1", status='A',
+ has_associated_marker=True, route='SRID=4326;LINESTRING(-1 1, 1 -1)')
+ route_1.categories.add(sub_categories[0])
+ routes.append(route_1)
+ route_2 = Route.objects.create(name="Route 2", status='A',
+ has_associated_marker=False, route='SRID=4326;LINESTRING(0 0, 2 2)')
+ route_2.categories.add(sub_categories[1])
+ routes.append(route_2)
+ return routes
+
class ImporterTest:
def test_get(self):
nb_by_cat = {}
@@ -198,10 +217,13 @@ class GeoRSSImporterTest(TestCase, ImporterTest):
def setUp(self):
subcategory_1, subcategory_2 = subcategory_setup()
importer1 = Importer.objects.create(importer_type='RSS',
- source=test_dir_path+'tests/georss.xml')
+ source=test_dir_path+'tests/georss_simple.xml')
importer1.categories.add(subcategory_1)
+ importer2 = Importer.objects.create(importer_type='RSS',
+ source=test_dir_path+'tests/eqs7day-M5.xml')
+ importer2.categories.add(subcategory_2)
- self.marker_importers = [(importer1, 1)]
+ self.marker_importers = [(importer1, 1), (importer2, 32)]
class FeedsTest(TestCase):
def setUp(self):
@@ -319,11 +341,15 @@ class AreaAdminFormTest(TestCase):
class DynamicCategoryTest(TestCase):
def setUp(self):
self.areas = areas_setup()
- self.markers = marker_setup()
+ subcategories = subcategory_setup()
+ self.markers = marker_setup(subcategories)
+ self.routes = route_setup(subcategories)
def test_dynamic_evaluation(self):
cats = self.areas[0].getCategories(status='A', filter_available=True)
self.assertEqual(len(cats), 1)
+ cats = self.areas[2].getCategories(status='A', filter_available=True)
+ self.assertEqual(len(cats), 2)
def test_get_all_categories(self):
url = reverse('chimere:get_all_categories')
@@ -351,13 +377,15 @@ class NewsTest(TestCase):
class RapprochementTest(TestCase):
def setUp(self):
self.areas = areas_setup()
- self.markers = marker_setup()
+ self.subcategories = subcategory_setup()
+ self.markers = marker_setup(self.subcategories)
+ self.routes = route_setup(self.subcategories)
self.adminuser = User.objects.create_superuser('admin',
'admin@test.com',
'pass')
self.client.login(username='admin', password='pass')
- def test_managed_modified(self):
+ def test_managed_modified_markers(self):
ref_marker = self.markers[0]
new_vals = {'name':"Marker 1 - modified",
'point':GEOSGeometry('SRID=4326;POINT(-4 48)')}
@@ -377,6 +405,30 @@ class RapprochementTest(TestCase):
for k in new_vals:
self.assertEqual(getattr(ref_marker, k), new_vals[k])
+ def test_managed_modified_routes(self):
+ ref_route = self.routes[0]
+ new_vals = {'name':"Route 1 - modified",
+ 'route':GEOSGeometry('SRID=4326;LINESTRING(1 1,2 2)')}
+ values = {'status':'M', 'ref_item':ref_route,
+ 'has_associated_marker':True}
+ values.update(new_vals)
+ modified_route = Route.objects.create(**values)
+ modified_route.categories.add(self.subcategories[1])
+ response = self.client.post('/admin/chimere/route/',
+ data={'action':['managed_modified'],
+ 'index':0, 'rapprochement':1,
+ 'name':1, 'route':1, 'categories':1,
+ '_selected_action':[unicode(ref_route.pk)]
+ })
+ ref_route = Route.objects.get(pk=ref_route.pk)
+ self.assertEqual(Route.objects.filter(ref_item=ref_route,
+ status='M').count(), 0)
+ self.assertEqual(ref_route.name, new_vals['name'])
+ self.assertEqual(ref_route.route.wkt, new_vals['route'].wkt)
+ self.assertEqual(ref_route.categories.all()[0], self.subcategories[1])
+ self.assertEqual(ref_route.associated_marker.all()[0].name,
+ ref_route.name)
+
class RouteTest(TestCase):
def setUp(self):
self.subcategories = subcategory_setup()
diff --git a/chimere/tests/data_license b/chimere/tests/data_license
new file mode 100644
index 0000000..bee3231
--- /dev/null
+++ b/chimere/tests/data_license
@@ -0,0 +1 @@
+eqs7day-M5.xml is a georss feed from the website http://www.usgs.gov/ published under the US public domain
diff --git a/chimere/tests/eqs7day-M5.xml b/chimere/tests/eqs7day-M5.xml
new file mode 100644
index 0000000..47c12b7
--- /dev/null
+++ b/chimere/tests/eqs7day-M5.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <channel>
+ <title>USGS M 5+ Earthquakes</title>
+ <description>Real-time, worldwide earthquake list for the past 7 days</description>
+ <link>http://earthquake.usgs.gov/earthquakes/</link>
+ <dc:publisher>U.S. Geological Survey</dc:publisher>
+ <pubDate>Fri, 23 Nov 2012 23:21:31 GMT</pubDate>
+ <item><pubDate>Fri, 23 Nov 2012 20:50:48 GMT</pubDate><title>M 5.0, Solomon Islands</title><description>November 23, 2012 20:50:48 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dxgz.php</link><geo:lat>-10.7326</geo:lat><geo:long>162.7787</geo:long><dc:subject>5</dc:subject><dc:subject>pastday</dc:subject><dc:subject>32.00 km</dc:subject><guid isPermaLink="false">usc000dxgz</guid></item>
+ <item><pubDate>Fri, 23 Nov 2012 20:21:28 GMT</pubDate><title>M 5.3, near the east coast of Honshu, Japan</title><description>November 23, 2012 20:21:28 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dxfu.php</link><geo:lat>38.2123</geo:lat><geo:long>141.8265</geo:long><dc:subject>5</dc:subject><dc:subject>pastday</dc:subject><dc:subject>47.00 km</dc:subject><guid isPermaLink="false">usc000dxfu</guid></item>
+ <item><pubDate>Fri, 23 Nov 2012 04:52:39 GMT</pubDate><title>M 5.2, Luzon, Philippines</title><description>November 23, 2012 04:52:39 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dx8j.php</link><geo:lat>14.0515</geo:lat><geo:long>120.7557</geo:long><dc:subject>5</dc:subject><dc:subject>pastday</dc:subject><dc:subject>199.70 km</dc:subject><guid isPermaLink="false">usc000dx8j</guid></item>
+ <item><pubDate>Fri, 23 Nov 2012 00:40:19 GMT</pubDate><title>M 5.0, Molucca Sea</title><description>November 23, 2012 00:40:19 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dx7p.php</link><geo:lat>1.6378</geo:lat><geo:long>125.8643</geo:long><dc:subject>5</dc:subject><dc:subject>pastday</dc:subject><dc:subject>57.50 km</dc:subject><guid isPermaLink="false">usc000dx7p</guid></item>
+ <item><pubDate>Thu, 22 Nov 2012 22:44:31 GMT</pubDate><title>M 5.0, southeast of the Loyalty Islands</title><description>November 22, 2012 22:44:31 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dx70.php</link><geo:lat>-22.3513</geo:lat><geo:long>174.0493</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>35.30 km</dc:subject><guid isPermaLink="false">usc000dx70</guid></item>
+ <item><pubDate>Thu, 22 Nov 2012 18:01:15 GMT</pubDate><title>M 5.0, southern Sumatra, Indonesia</title><description>November 22, 2012 18:01:15 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dx58.php</link><geo:lat>-4.5417</geo:lat><geo:long>102.8549</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>77.80 km</dc:subject><guid isPermaLink="false">usc000dx58</guid></item>
+ <item><pubDate>Thu, 22 Nov 2012 13:07:05 GMT</pubDate><title>M 5.6, Salta, Argentina</title><description>November 22, 2012 13:07:05 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dx1i.php</link><geo:lat>-22.6657</geo:lat><geo:long>-63.4880</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>459.10 km</dc:subject><guid isPermaLink="false">usc000dx1i</guid></item>
+ <item><pubDate>Thu, 22 Nov 2012 09:09:31 GMT</pubDate><title>M 5.0, Bali region, Indonesia</title><description>November 22, 2012 09:09:31 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwzh.php</link><geo:lat>-8.9069</geo:lat><geo:long>115.1527</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>73.80 km</dc:subject><guid isPermaLink="false">usc000dwzh</guid></item>
+ <item><pubDate>Thu, 22 Nov 2012 05:21:49 GMT</pubDate><title>M 5.2, Komandorskiye Ostrova, Russia region</title><description>November 22, 2012 05:21:49 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwta.php</link><geo:lat>54.0864</geo:lat><geo:long>168.3012</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>30.00 km</dc:subject><guid isPermaLink="false">usc000dwta</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 22:52:28 GMT</pubDate><title>M 5.2, offshore Libertador O'Higgins, Chile</title><description>November 21, 2012 22:52:28 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwl3.php</link><geo:lat>-33.9846</geo:lat><geo:long>-72.0118</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>9.80 km</dc:subject><guid isPermaLink="false">usc000dwl3</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 21:36:22 GMT</pubDate><title>M 5.9, offshore Libertador O'Higgins, Chile</title><description>November 21, 2012 21:36:22 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwip.php</link><geo:lat>-34.0163</geo:lat><geo:long>-72.0172</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>15.70 km</dc:subject><guid isPermaLink="false">usc000dwip</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 18:16:36 GMT</pubDate><title>M 5.1, offshore Libertador O'Higgins, Chile</title><description>November 21, 2012 18:16:36 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwbj.php</link><geo:lat>-33.9622</geo:lat><geo:long>-72.1422</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>9.70 km</dc:subject><guid isPermaLink="false">usc000dwbj</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 17:42:37 GMT</pubDate><title>M 5.0, near the east coast of Honshu, Japan</title><description>November 21, 2012 17:42:37 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dwai.php</link><geo:lat>38.4991</geo:lat><geo:long>141.7353</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>37.30 km</dc:subject><guid isPermaLink="false">usc000dwai</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 16:46:37 GMT</pubDate><title>M 5.4, south of Sumbawa, Indonesia</title><description>November 21, 2012 16:46:37 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dw8j.php</link><geo:lat>-11.3754</geo:lat><geo:long>117.9300</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>9.90 km</dc:subject><guid isPermaLink="false">usc000dw8j</guid></item>
+ <item><pubDate>Wed, 21 Nov 2012 01:18:40 GMT</pubDate><title>M 5.0, New Britain region, Papua New Guinea</title><description>November 21, 2012 01:18:40 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dvz8.php</link><geo:lat>-5.9033</geo:lat><geo:long>151.7074</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>8.40 km</dc:subject><guid isPermaLink="false">usc000dvz8</guid></item>
+ <item><pubDate>Tue, 20 Nov 2012 17:08:59 GMT</pubDate><title>M 5.2, Taiwan region</title><description>November 20, 2012 17:08:59 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dvkl.php</link><geo:lat>22.4104</geo:lat><geo:long>121.4210</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>11.40 km</dc:subject><guid isPermaLink="false">usc000dvkl</guid></item>
+ <item><pubDate>Tue, 20 Nov 2012 16:23:24 GMT</pubDate><title>M 5.4, offshore Libertador O'Higgins, Chile</title><description>November 20, 2012 16:23:24 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dvj3.php</link><geo:lat>-33.9579</geo:lat><geo:long>-72.3163</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>15.40 km</dc:subject><guid isPermaLink="false">usc000dvj3</guid></item>
+ <item><pubDate>Tue, 20 Nov 2012 15:27:59 GMT</pubDate><title>M 5.0, Molucca Sea</title><description>November 20, 2012 15:27:59 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dvi3.php</link><geo:lat>0.8083</geo:lat><geo:long>126.0539</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>9.90 km</dc:subject><guid isPermaLink="false">usc000dvi3</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 17:54:08 GMT</pubDate><title>M 5.4, Pakistan</title><description>November 19, 2012 17:54:08 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000duzz.php</link><geo:lat>30.4539</geo:lat><geo:long>67.5394</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>14.10 km</dc:subject><guid isPermaLink="false">usc000duzz</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 16:45:50 GMT</pubDate><title>M 5.2, offshore Libertador O'Higgins, Chile</title><description>November 19, 2012 16:45:50 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000duxx.php</link><geo:lat>-33.9382</geo:lat><geo:long>-72.1818</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>10.00 km</dc:subject><guid isPermaLink="false">usc000duxx</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 10:55:08 GMT</pubDate><title>M 5.2, New Britain region, Papua New Guinea</title><description>November 19, 2012 10:55:08 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000duuj.php</link><geo:lat>-5.8731</geo:lat><geo:long>151.6449</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>10.00 km</dc:subject><guid isPermaLink="false">usc000duuj</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 10:15:54 GMT</pubDate><title>M 5.1, New Britain region, Papua New Guinea</title><description>November 19, 2012 10:15:54 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dutx.php</link><geo:lat>-5.9073</geo:lat><geo:long>151.7066</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>12.80 km</dc:subject><guid isPermaLink="false">usc000dutx</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 10:09:46 GMT</pubDate><title>M 5.0, south of Java, Indonesia</title><description>November 19, 2012 10:09:46 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000duty.php</link><geo:lat>-9.5383</geo:lat><geo:long>108.2428</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>34.90 km</dc:subject><guid isPermaLink="false">usc000duty</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 09:44:34 GMT</pubDate><title>M 5.8, New Britain region, Papua New Guinea</title><description>November 19, 2012 09:44:34 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000duti.php</link><geo:lat>-5.7339</geo:lat><geo:long>151.6063</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>10.10 km</dc:subject><guid isPermaLink="false">usc000duti</guid></item>
+ <item><pubDate>Mon, 19 Nov 2012 04:09:27 GMT</pubDate><title>M 5.1, east of the South Sandwich Islands</title><description>November 19, 2012 04:09:27 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000durc.php</link><geo:lat>-59.3483</geo:lat><geo:long>-18.3098</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>6.50 km</dc:subject><guid isPermaLink="false">usc000durc</guid></item>
+ <item><pubDate>Sun, 18 Nov 2012 20:01:26 GMT</pubDate><title>M 5.1, Mindanao, Philippines</title><description>November 18, 2012 20:01:26 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dunk.php</link><geo:lat>6.0242</geo:lat><geo:long>125.8842</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>126.10 km</dc:subject><guid isPermaLink="false">usc000dunk</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 18:43:52 GMT</pubDate><title>M 5.3, West Chile Rise</title><description>November 17, 2012 18:43:52 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dubt.php</link><geo:lat>-37.0202</geo:lat><geo:long>-94.9667</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>10.80 km</dc:subject><guid isPermaLink="false">usc000dubt</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 18:12:21 GMT</pubDate><title>M 5.4, West Chile Rise</title><description>November 17, 2012 18:12:21 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000dub9.php</link><geo:lat>-37.1596</geo:lat><geo:long>-94.9680</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>10.10 km</dc:subject><guid isPermaLink="false">usc000dub9</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 09:06:26 GMT</pubDate><title>M 5.1, southeast of the Loyalty Islands</title><description>November 17, 2012 09:06:26 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000du6f.php</link><geo:lat>-22.2351</geo:lat><geo:long>171.6432</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>115.10 km</dc:subject><guid isPermaLink="false">usc000du6f</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 05:29:45 GMT</pubDate><title>M 5.0, Fiji region</title><description>November 17, 2012 05:29:45 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000du4e.php</link><geo:lat>-20.2516</geo:lat><geo:long>-178.4418</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>583.80 km</dc:subject><guid isPermaLink="false">usc000du4e</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 05:12:56 GMT</pubDate><title>M 6.1, Tonga region</title><description>November 17, 2012 05:12:56 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000du43.php</link><geo:lat>-18.3108</geo:lat><geo:long>-172.3741</geo:long><dc:subject>6</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>9.80 km</dc:subject><guid isPermaLink="false">usc000du43</guid></item>
+ <item><pubDate>Sat, 17 Nov 2012 02:51:24 GMT</pubDate><title>M 5.7, Vanuatu</title><description>November 17, 2012 02:51:24 GMT</description><link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/usc000du3a.php</link><geo:lat>-15.0263</geo:lat><geo:long>167.4260</geo:long><dc:subject>5</dc:subject><dc:subject>pastweek</dc:subject><dc:subject>128.40 km</dc:subject><guid isPermaLink="false">usc000du3a</guid></item>
+ </channel>
+</rss>
diff --git a/chimere/tests/georss.xml b/chimere/tests/georss_simple.xml
index 8697f16..8697f16 100644
--- a/chimere/tests/georss.xml
+++ b/chimere/tests/georss_simple.xml
diff --git a/chimere/urls.py b/chimere/urls.py
index 1ccabd4..aa95921 100644
--- a/chimere/urls.py
+++ b/chimere/urls.py
@@ -31,7 +31,7 @@ def i18n_javascript(request):
urlpatterns = patterns('chimere.views',
- url(r'^simple(/?P<area_name>[a-zA-Z0-9_-]+)?$', 'index', {'simple':True},
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?simple$', 'index', {'simple':True},
name="simple_index")
)
diff --git a/chimere/utils.py b/chimere/utils.py
index 42f3b06..4a12e37 100644
--- a/chimere/utils.py
+++ b/chimere/utils.py
@@ -67,7 +67,7 @@ class ImportManager:
def get(self):
pass
- def put(self):
+ def put(self, extra_args={}):
pass
def create_or_update_item(self, cls, values, import_key, version=None,
@@ -323,6 +323,10 @@ class ShapefileManager(ImportManager):
if not srid:
# try with the default projection
srid = settings.CHIMERE_EPSG_DISPLAY_PROJECTION
+ msg = _(u"SRID cannot be guessed. The default SRID (%s) has "
+ u"been used.") % srid
+ #If imported items are not well located "
+ # u"ask your data provider for the SRID to use.") % srid
shapefilename = tmpdir + os.sep + sources[0]
ds = DataSource(shapefilename)
lyr = ds[0]
@@ -569,17 +573,22 @@ class GeoRSSManager(ImportManager):
if feed['bozo']:
return (0, 0, _(u"RSS feed is not well formed"))
for item in feed['items']:
- if "georss_point" not in item and 'georss_line' not in item:
+ if "georss_point" not in item and 'georss_line' not in item \
+ and not ("geo_lat" in item and "geo_long" in item):
continue
cls = None
dct = {'origin':self.importer_instance.origin,
'license':self.importer_instance.license}
- if 'georss_point' in item:
+ if 'georss_point' in item or "geo_lat" in item:
cls = Marker
- try:
- y, x = item['georss_point'].split(' ')
- except ValueError:
- continue
+ if 'georss_point' in item:
+ try:
+ y, x = item['georss_point'].split(' ')
+ except ValueError:
+ continue
+ else:
+ y = item['geo_lat']
+ x = item['geo_long']
dct['point'] = 'SRID=4326;POINT(%s %s)' % (x, y)
for k in ['description', 'summary', 'value']:
if k in item:
@@ -716,7 +725,7 @@ class OSMManager(ImportManager):
items.append(item)
return (new_item, updated_item, msg)
- def put(self):
+ def put(self, extra_args={}):
# first of all: reimport in order to verify that no changes has been
# made since the last import
from models import Marker
@@ -730,14 +739,26 @@ class OSMManager(ImportManager):
return 0, _(u"There are items from a former import not yet "
u"validated - validate them before exporting")
# start import
- api = OsmApi.OsmApi(api=settings.CHIMERE_OSM_API_URL,
- username=settings.CHIMERE_OSM_USER,
- password=settings.CHIMERE_OSM_PASSWORD)
+ api = settings.CHIMERE_OSM_API_URL
+ username = settings.CHIMERE_OSM_USER
+ password = settings.CHIMERE_OSM_PASSWORD
+ if extra_args:
+ try:
+ api = extra_args['api']
+ username = extra_args['username']
+ password = extra_args['password']
+ except KeyError:
+ return 0, _(u"Bad params - programming error")
+ username = username.encode('latin1')
+ password = password.encode('latin1')
+ api = OsmApi.OsmApi(api=api, username=username, password=password)
api.ChangesetCreate({u"comment": u"Import from Chimère %s" % \
get_version()})
hooks = RE_HOOK.findall(self.importer_instance.filtr)
if not hooks:
- return 0, _(u"Bad param")
+ hooks = RE_HOOK.findall(self.importer_instance.source)
+ if not hooks:
+ return 0, _(u"Bad param")
tags = {}
bbox = []
for hook in hooks:
diff --git a/chimere/views.py b/chimere/views.py
index 4dd6462..b40e58a 100644
--- a/chimere/views.py
+++ b/chimere/views.py
@@ -227,7 +227,6 @@ def get_edit_page(redirect_url, item_cls, item_form,
init_item.submiter_session_key == \
request.session.session_key):
inst = init_item
-
form = item_form(request.POST, request.FILES, instance=inst,
subcategories=listed_subcats)
formset_multi = multimediafile_formset(request.POST, request.FILES,
@@ -246,6 +245,9 @@ def get_edit_page(redirect_url, item_cls, item_form,
item.ref_item = ref_item
if item.pk != ref_item.pk:
item.status = 'M'
+ if hasattr(ref_item, 'has_associated_marker'):
+ item.has_associated_marker = \
+ ref_item.has_associated_marker
elif not item.ref_item:
# initialisation
item.ref_item = item
@@ -629,17 +631,19 @@ def get_all_categories(request, area_name=None):
return HttpResponse(jsons)
def get_available_categories(request, area_name=None, area=None, status='A',
- force=None):
+ force=None):
'''
Get category menu for a designed area
'''
context_data, redir = get_base_response(area_name)
area = context_data["area"]
- if area and area.dynamic_categories and \
- not "current_extent" in request.GET:
- return ""
if redir:
return redir
+ if area and area.dynamic_categories and \
+ not "current_extent" in request.GET:
+ context_data['sub_categories'] = []
+ return render_to_response('chimere/blocks/categories.html', context_data,
+ context_instance=RequestContext(request))
if not area or not area.dynamic_categories:
# Categories are not updated dynamicaly when the user move the map
# so we return ALL the categories
diff --git a/chimere/widgets.py b/chimere/widgets.py
index 185d134..481a5c9 100644
--- a/chimere/widgets.py
+++ b/chimere/widgets.py
@@ -33,6 +33,8 @@ from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
+import re
+
def getMapJS(area_name=''):
'''Variable initialization for drawing the map
'''
@@ -144,6 +146,13 @@ class ButtonSelectWidget(forms.RadioSelect):
u"</script>\n</div>\n" % kwargs['attrs']['id']
return mark_safe(rendered)
+class ImporterChoicesWidget(forms.Select):
+ '''
+ Importer select widget.
+ '''
+ class Media:
+ js = ["%schimere/js/importer_interface.js" % settings.STATIC_URL,]
+
class TextareaWidgetBase(forms.Textarea):
"""
Manage the edition of a text using TinyMCE
@@ -290,7 +299,7 @@ class PointChooserWidget(forms.TextInput):
#TODO: manage area
tpl = u"<script type='text/javascript'><!--\n"\
u"%s// !--></script>\n" % js
- tpl += u"<div id='map_edit'></div>"\
+ tpl += u"</div><div id='map_edit'></div>"\
u"<div id='live_lonlat'>"\
u" <p><label for='live_latitude'>%s</label>"\
u" <input type='texte' name='live_latitude' id='live_latitude' "\
@@ -298,7 +307,6 @@ class PointChooserWidget(forms.TextInput):
u"<p><label for='live_longitude'>%s</label><input type='texte' "\
u"name='live_longitude' id='live_longitude' size='8' "\
u"disabled='true' value='%f'/></p>"\
- u"</div>"\
u"<input type='hidden' name='%s' id='id_%s' value='%s'/>" % (
_("Latitude"), value_y, _("Longitude"), value_x, name, name,
val)
@@ -310,8 +318,7 @@ class PointChooserWidget(forms.TextInput):
u' mylonlat.transform(EPSG_DISPLAY_PROJECTION, \n'\
u' EPSG_PROJECTION), true);\n' % (
value_x, value_y)
- tpl += "// --></script>\n"\
- u"<hr class='spacer'/>\n"
+ tpl += "// --></script>\n"
return mark_safe(tpl)
class PointField(models.PointField):
@@ -477,34 +484,44 @@ class AreaWidget(forms.TextInput):
"%schimere/js/edit_area.js" % settings.STATIC_URL,
"%schimere/js/base.js" % settings.STATIC_URL,]
- def render(self, name, value, attrs=None):
+ def get_bounding_box_from_value(self, value):
+ '''
+ Return upper left lat/lon and lower lat/lon from the input value
+ '''
+ upper_left_lat, upper_left_lon = 0, 0
+ lower_right_lat, lower_right_lon = 0, 0
+ if not value:
+ return upper_left_lat, upper_left_lon, lower_right_lat, \
+ lower_right_lon
+ if len(value) == 2:
+ upper_left = value[0]
+ lower_right = value[1]
+ if hasattr(upper_left, 'x') and hasattr(upper_left, 'y'):
+ upper_left_lon, upper_left_lat = upper_left.x, upper_left.y
+ elif len(upper_left) == 2:
+ try:
+ upper_left_lon = float(upper_left[0])
+ upper_left_lat = float(upper_left[1])
+ except ValueError:
+ pass
+ if hasattr(lower_right, 'x') and hasattr(lower_right, 'y'):
+ lower_right_lon, lower_right_lat = lower_right.x, \
+ lower_right.y
+ elif len(lower_right) == 2:
+ lower_right_lon, lower_right_lat = lower_right
+ try:
+ lower_right_lon = float(lower_right[0])
+ lower_right_lat = float(lower_right[1])
+ except ValueError:
+ pass
+ return upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon
+
+ def render(self, name, value, attrs=None, initialized=True):
"""
Render a map
"""
- upper_left_lat, upper_left_lon = 0, 0
- lower_right_lat, lower_right_lon = 0, 0
- if value:
- if len(value) == 2:
- upper_left = value[0]
- lower_right = value[1]
- if hasattr(upper_left, 'x') and hasattr(upper_left, 'y'):
- upper_left_lon, upper_left_lat = upper_left.x, upper_left.y
- elif len(upper_left) == 2:
- try:
- upper_left_lon = float(upper_left[0])
- upper_left_lat = float(upper_left[1])
- except ValueError:
- pass
- if hasattr(lower_right, 'x') and hasattr(lower_right, 'y'):
- lower_right_lon, lower_right_lat = lower_right.x, \
- lower_right.y
- elif len(lower_right) == 2:
- lower_right_lon, lower_right_lat = lower_right
- try:
- lower_right_lon = float(lower_right[0])
- lower_right_lat = float(lower_right[1])
- except ValueError:
- pass
+ upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon = \
+ self.get_bounding_box_from_value(value)
tpl = getMapJS()
tpl += u"</div>\n"\
u"<input type='hidden' name='upper_left_lat' id='upper_left_lat' "\
@@ -517,9 +534,9 @@ class AreaWidget(forms.TextInput):
u"value='%f'/>\n" % (
upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon)
help_msg = _(u"Hold CTRL, click and drag to select area on the map")
- tpl += u"<p>%s</p>\n" % help_msg
+ tpl += u"<p class='help-osm'>%s</p>\n" % help_msg
tpl += u"<script type='text/javascript'>\n"
- tpl += u"$(document).ready(function($) {\ninit();\n"
+ tpl += u"function init_map_form (){\ninit();\n"
if value:
tpl += u"var extent = new OpenLayers.Bounds(%f, %f, %f, %f);\n"\
u"extent.transform(epsg_display_projection, epsg_projection);\n"\
@@ -527,7 +544,10 @@ class AreaWidget(forms.TextInput):
u"map.zoomToExtent(extent, true);\n"\
u"map.zoomOut();" % (upper_left_lon, upper_left_lat,
lower_right_lon, lower_right_lat)
- tpl += u"});\n</script>\n<hr class='spacer'/>\n"
+ tpl += u"}\n"
+ if initialized:
+ tpl += u"$(document).ready(function($) {init_map_form()});\n"
+ tpl += u"</script>\n"
tpl += u"<div id='map_edit'>\n"
return mark_safe(tpl)
@@ -547,6 +567,100 @@ class AreaWidget(forms.TextInput):
values.append(value)
return values
+RE_XAPI = re.compile('(node|way)\[(.*=.*)\]\[bbox='\
+ '(-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*)\]')
+
+class ImportFiltrWidget(AreaWidget):
+ """
+ Manage the edition of the import source field
+ """
+ class Media:
+ css = {
+ "all": settings.OSM_CSS_URLS + \
+ ["%schimere/css/forms.css" % settings.STATIC_URL,]
+ }
+ js = settings.OSM_JS_URLS + [
+ "%schimere/js/edit_area.js" % settings.STATIC_URL,
+ "%schimere/js/base.js" % settings.STATIC_URL,]
+
+ def render(self, name, value, attrs=None):
+ """
+ Render a map
+ """
+ tpl = super(ImportFiltrWidget, self).render(name, value, attrs,
+ initialized=False)
+ tpl += u"</div><hr class='spacer'/>"
+ vals = {'lbl':_(u"Type:"), 'name':name, 'node':_(u"Node"),
+ 'way':_(u"Way")}
+ vals['way_selected'] = ' checked="checked"'\
+ if self.xapi_type == 'way' else ''
+ vals['node_selected'] = ' checked="checked"'\
+ if self.xapi_type == 'node' else ''
+ tpl += u"<div class='input-osm'><label>%(lbl)s</label>"\
+ u"<input type='radio' name='id_%(name)s_type' id='id_%(name)s_node'"\
+ u" value='node'%(node_selected)s/> <label for='id_%(name)s_node'>"\
+ u"%(node)s</label> <input type='radio' name='id_%(name)s_type' "\
+ u"id='id_%(name)s_way' value='way'%(way_selected)s/> <label "\
+ u"for='id_%(name)s_way'>%(way)s</label></div>" % vals
+ help_msg = _(u"Enter an OSM \"tag=value\" string such as "\
+ u"\"amenity=pub\". A list of common tag is available "\
+ u"<a href='https://wiki.openstreetmap.org/wiki/Map_Features' "\
+ u" target='_blank'>here</a>.")
+ tpl += u"<p class='help-osm'>%s</p>\n" % help_msg
+ tpl += u"<div class='input-osm'><label for='id_%s_tag'>%s</label>"\
+ u"<input type='text' id='id_%s_tag' value=\"%s\"/></div>" % (
+ name, _(u"Tag:"), name, self.xapi_tag)
+ tpl += u"<script type='text/javascript'>\n"
+ tpl += u"var default_xapi='%s';" % settings.CHIMERE_XAPI_URL
+ tpl += u'var msg_missing_area = "%s";' % \
+ _(u"You have to select an area.")
+ tpl += u'var msg_missing_type = "%s";' % \
+ _(u"You have to select a type.")
+ tpl += u'var msg_missing_filtr = "%s";' % \
+ _(u"You have to insert a filter tag.")
+ tpl += u"</script>\n"
+ help_msg = _(u"If you change the above form don't forget to refresh "\
+ u"before submit!")
+ tpl += u"<p class='help-osm errornote'>%s</p>\n" % help_msg
+ help_msg = _(u"You can put a Folder name of the KML file to filter on "\
+ u"it.")
+ tpl += u"<p class='help-kml'>%s</p>\n" % help_msg
+ if not value:
+ value = ''
+ tpl += u"<div><input type='text' id='id_%s' name='id_%s' "\
+ u"value=\"%s\"/> <input type='button' id='id_refresh_%s' "\
+ u"value='%s' class='input-osm'/>" % (name, name, value, name,
+ _(u"Refresh"))
+ return mark_safe(tpl)
+
+ def value_from_datadict(self, data, files, name):
+ """
+ Return the appropriate values
+ """
+ return data.get('id_'+name, None)
+
+ def get_bounding_box_from_value(self, value):
+ '''
+ Return upper left lat/lon, lower lat/lon from the input value.
+ Get also xapi type and xapi tag
+ '''
+ upper_left_lat, upper_left_lon = 0, 0
+ lower_right_lat, lower_right_lon = 0, 0
+ self.xapi_type, self.xapi_tag, self.bounding_box = None, '', None
+ if not value:
+ return upper_left_lat, upper_left_lon, lower_right_lat, \
+ lower_right_lon
+ xapi_m = RE_XAPI.match(value)
+ if not xapi_m:
+ return upper_left_lat, upper_left_lon, lower_right_lat, \
+ lower_right_lon
+ # as the regexp pass, we could be pretty confident
+ self.xapi_type, self.xapi_tag, self.bounding_box = xapi_m.groups()
+ upper_left_lon, lower_right_lat, lower_right_lon, upper_left_lat = \
+ self.bounding_box.split(',')
+ return float(upper_left_lat), float(upper_left_lon), \
+ float(lower_right_lat), float(lower_right_lon)
+
class AreaField(forms.MultiValueField):
'''
Set the widget for the form field