summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chimere/fixtures/initial_data.json8
-rw-r--r--chimere/forms.py18
-rw-r--r--chimere/locale/fr/LC_MESSAGES/django.po278
-rw-r--r--chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py224
-rw-r--r--chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py241
-rw-r--r--chimere/models.py27
-rw-r--r--chimere/static/chimere/css/styles.css97
-rw-r--r--chimere/static/chimere/img/layer-switcher-maximize.pngbin566 -> 372 bytes
-rw-r--r--chimere/static/chimere/img/layer-switcher-minimize.pngbin249 -> 257 bytes
-rw-r--r--chimere/static/chimere/img/map_sprite.pngbin0 -> 7924 bytes
-rw-r--r--chimere/static/chimere/js/SimplePanZoom.js362
-rw-r--r--chimere/static/chimere/js/jquery.chimere.js19
-rw-r--r--chimere/templates/chimere/edit.html56
-rw-r--r--chimere/views.py22
-rw-r--r--chimere/widgets.py2
-rw-r--r--debian/control3
-rw-r--r--docs/install.rst4
-rw-r--r--docs/upgrade.rst5
-rw-r--r--example_project/settings.py1
-rw-r--r--requirements.txt1
20 files changed, 1224 insertions, 144 deletions
diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json
index 9816932..fe1cc98 100644
--- a/chimere/fixtures/initial_data.json
+++ b/chimere/fixtures/initial_data.json
@@ -254,5 +254,13 @@
"layer_code": "new OpenLayers.Layer.OSM.TransportMap(\"Transport map\",\r\n{attribution:\"Tiles courtesy of <a href='http://www.opencyclemap.org/' target='_blank'>Andy Allan</a>\",\r\nkeyid:\"transportmap\",displayOutsideMaxExtent:!0,wrapDateLine:!0,layerCode:\"T\"})",
"name": "OSM - TransportMap"
}
+ },
+ {
+ "pk": 4,
+ "model": "chimere.layer",
+ "fields": {
+ "layer_code": "new OpenLayers.Layer.MapQuestOSM()",
+ "name": "OSM - MapQuest"
+ }
}
]
diff --git a/chimere/forms.py b/chimere/forms.py
index c036911..f49a903 100644
--- a/chimere/forms.py
+++ b/chimere/forms.py
@@ -124,10 +124,11 @@ class MarkerAdminFormBase(forms.ModelForm):
"""
Custom initialization method in order to manage properties
"""
+ self.pms = [pm for pm in PropertyModel.objects.filter(available=True)]
if 'instance' in keys and keys['instance']:
instance = keys['instance']
property_dct = {}
- for pm in PropertyModel.objects.filter(available=True):
+ for pm in self.pms:
property = instance.getProperty(pm)
if property:
property_dct[pm.getNamedId()] = property.value
@@ -147,6 +148,8 @@ class MarkerAdminFormBase(forms.ModelForm):
def clean(self):
'''
Verify that a start date is provided when an end date is set
+ Verify the mandatory properties (to be check manualy because it depends
+ on the checked categories)
'''
if not settings.CHIMERE_DAYS_BEFORE_EVENT:
return self.cleaned_data
@@ -155,6 +158,19 @@ class MarkerAdminFormBase(forms.ModelForm):
msg = _(u"End date has been set with no start date")
self._errors["end_date"] = self.error_class([msg])
del self.cleaned_data['end_date']
+
+ for pm in self.pms:
+ if not pm.mandatory or self.cleaned_data[pm.getNamedId()]:
+ continue
+ pm_cats = pm.subcategories.all()
+ print self.cleaned_data['categories']
+ print pm_cats
+ if not pm_cats or \
+ [submited_cat for submited_cat in self.cleaned_data['categories']
+ if submited_cat in pm_cats]:
+ msg = _(u"This field is mandatory for the selected categories")
+ self._errors[pm.getNamedId()] = self.error_class([msg])
+ #raise forms.ValidationError()
return self.cleaned_data
def save(self, *args, **keys):
diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po
index 9335b42..b986cf5 100644
--- a/chimere/locale/fr/LC_MESSAGES/django.po
+++ b/chimere/locale/fr/LC_MESSAGES/django.po
@@ -7,18 +7,18 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 13:12+0200\n"
+"POT-Creation-Date: 2012-08-22 14:54+0200\n"
"PO-Revision-Date: 2010-03-20 20:00+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:490
+#: __init__.py:8 models.py:502
msgid "Multimedia files"
msgstr "Fichiers multimedias"
-#: __init__.py:9 models.py:539
+#: __init__.py:9 models.py:551
msgid "Picture files"
msgstr "Fichiers d'image"
@@ -107,365 +107,373 @@ msgstr "Courriel (optionnel) "
msgid "Object"
msgstr "Objet"
-#: forms.py:155
+#: forms.py:158
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:369
+#: forms.py:171
+msgid "This field is mandatory for the selected categories"
+msgstr "Ce champ est obligatoire pour les catégories sélectionnées"
+
+#: forms.py:385
msgid "File"
msgstr "Fichier"
-#: forms.py:375
+#: forms.py:391
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:380 models.py:48 models.py:101 models.py:122 models.py:135
-#: models.py:149 models.py:232 models.py:437 models.py:480 models.py:524
-#: models.py:555 models.py:792 models.py:804 models.py:889
+#: forms.py:396 models.py:49 models.py:102 models.py:123 models.py:136
+#: models.py:150 models.py:233 models.py:449 models.py:492 models.py:536
+#: models.py:567 models.py:804 models.py:816 models.py:901
#: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36
msgid "Name"
msgstr "Nom"
-#: forms.py:389 models.py:841
+#: forms.py:405 models.py:853
msgid "Area"
msgstr "Zone"
-#: forms.py:445
+#: forms.py:461
msgid "Start"
msgstr "Départ"
-#: forms.py:446
+#: forms.py:462
msgid "Finish"
msgstr "Arrivée :"
-#: forms.py:447
+#: forms.py:463
msgid "Speed"
msgstr "Vitesse"
-#: models.py:49 models.py:123 models.py:150 models.py:241 models.py:441
-#: models.py:810 models.py:891
+#: models.py:50 models.py:124 models.py:151 models.py:244 models.py:453
+#: models.py:822 models.py:903
msgid "Available"
msgstr "Disponible"
-#: models.py:50
+#: models.py:51 models.py:912
msgid "Date"
msgstr "Date"
-#: models.py:56 models.py:57
+#: models.py:57 models.py:58
msgid "News"
msgstr "Nouvelle"
-#: models.py:62
+#: models.py:63
msgid "Parameters"
msgstr "Paramètres"
-#: models.py:66
+#: models.py:67
msgid "TinyUrl"
msgstr "Mini-url"
-#: models.py:105 models.py:112 models.py:152
+#: models.py:106 models.py:113 models.py:153
msgid "Color theme"
msgstr "Thème de couleur"
-#: models.py:110
+#: models.py:111
msgid "Code"
msgstr "Code"
-#: models.py:111 models.py:124 models.py:154 models.py:482 models.py:531
-#: models.py:809 models.py:878 models.py:890
+#: models.py:112 models.py:125 models.py:155 models.py:494 models.py:543
+#: models.py:821 models.py:890 models.py:902
msgid "Order"
msgstr "Ordre"
-#: models.py:117
+#: models.py:118
msgid "Color"
msgstr "Couleur"
-#: models.py:130 models.py:148 templates/chimere/main_map.html:13
+#: models.py:131 models.py:149 templates/chimere/main_map.html:13
msgid "Category"
msgstr "Catégorie"
-#: models.py:136 models.py:433 models.py:525 models.py:620
+#: models.py:137 models.py:445 models.py:537 models.py:632
msgid "Image"
msgstr "Image"
-#: models.py:138 models.py:527 models.py:622
+#: models.py:139 models.py:539 models.py:634
msgid "Height"
msgstr "Hauteur"
-#: models.py:139 models.py:528 models.py:623
+#: models.py:140 models.py:540 models.py:635
msgid "Width"
msgstr "Largeur"
-#: models.py:143 models.py:151
+#: models.py:144 models.py:152
msgid "Icon"
msgstr "Icône"
-#: models.py:155
+#: models.py:156
msgid "Marker"
msgstr "Point d'intérêt"
-#: models.py:156 models.py:616 models.py:631
+#: models.py:157 models.py:628 models.py:643
#: templates/chimere/edit_route.html:27
msgid "Route"
msgstr "Trajet"
-#: models.py:157
+#: models.py:158
msgid "Both"
msgstr "Mixte"
-#: models.py:158
+#: models.py:159
msgid "Item type"
msgstr "Type d'élément"
-#: models.py:163
+#: models.py:164
msgid "Sub-category"
msgstr "Sous-catégorie"
-#: models.py:164
+#: models.py:165
msgid "Sub-categories"
msgstr "Sous-catégories"
-#: models.py:210
+#: models.py:211
msgid "Importer type"
msgstr "Type d'import"
-#: models.py:213 models.py:252
+#: models.py:214 models.py:255
msgid "Source"
msgstr "Source"
-#: models.py:215
+#: models.py:216
msgid "Filter"
msgstr "Filtre"
-#: models.py:218
+#: models.py:219
msgid "Associated subcategories"
msgstr "Sous-catégories associées"
-#: models.py:219
+#: models.py:220
msgid "State"
msgstr "État"
-#: models.py:221
+#: models.py:222
msgid "SRID"
msgstr "SRID"
-#: models.py:222
+#: models.py:223
msgid "Zipped file"
msgstr "Fichier zippé"
-#: models.py:225
+#: models.py:226
msgid "Importer"
msgstr "Import"
-#: models.py:234
+#: models.py:235
msgid "Submitter session key"
msgstr "Clé de session du demandeur"
-#: models.py:236
+#: models.py:237
+msgid "Submitter name or nickname"
+msgstr "Nom ou pseudo du demandeur"
+
+#: models.py:239
msgid "Submitter email"
msgstr "Courriel du demandeur"
-#: models.py:238
+#: models.py:241
msgid "Submitter comment"
msgstr "Commentaire du demandeur"
-#: models.py:240
+#: models.py:243
msgid "Submited"
msgstr "Soumis"
-#: models.py:242
+#: models.py:245
msgid "Modified"
msgstr "Modifié"
-#: models.py:243
+#: models.py:246
msgid "Disabled"
msgstr "Désactivé"
-#: models.py:244
+#: models.py:247
msgid "Imported"
msgstr "Importé"
-#: models.py:245
+#: models.py:248
msgid "Excluded"
msgstr "Exclu"
-#: models.py:247
+#: models.py:250
msgid "Status"
msgstr "État"
-#: models.py:248
+#: models.py:251
msgid "Import key"
msgstr "Clé d'import"
-#: models.py:250
+#: models.py:253
msgid "Import version"
msgstr "Version de l'import"
-#: models.py:255 templates/chimere/edit.html:56
+#: models.py:258 templates/chimere/edit.html:56
#: templates/chimere/edit_route.html:52
msgid "Start date"
msgstr "Date de début"
-#: models.py:256
+#: models.py:259
msgid "Not mandatory. Set it for dated item such as event. Format YYYY-MM-DD"
msgstr ""
"Optionnel. Précisez ce champ pour les éléments datés comme un événement. "
"Format du champ : AAAA-MM-JJ"
-#: models.py:258 templates/chimere/edit.html:62
+#: models.py:261 templates/chimere/edit.html:62
#: templates/chimere/edit_route.html:58
msgid "End date"
msgstr "Date de fin"
-#: models.py:259
+#: models.py:262
msgid ""
"Not mandatory. Set it only if you have a multi-day event. Format YYYY-MM-DD"
msgstr ""
"Optionnel. Précisez ce champ seulement pour des événements durant plusieurs "
"jours. Format du champ : AAAA-MM-JJ"
-#: models.py:291
+#: models.py:294
msgid "Reference marker"
msgstr "Point d'intérêt de référence"
-#: models.py:292
+#: models.py:295
msgid "Localisation"
msgstr "Localisation"
-#: models.py:294
+#: models.py:297
msgid "Available Date"
msgstr "Date de mise en disponibilité"
-#: models.py:298 templates/chimere/edit.html:49
+#: models.py:301 templates/chimere/edit.html:49
#: templates/chimere/edit_route.html:46
msgid "Description"
msgstr "Description"
-#: models.py:337 models.py:913
+#: models.py:349 models.py:932
msgid "Point of interest"
msgstr "Point d'intérêt"
-#: models.py:431
+#: models.py:443
msgid "Audio"
msgstr "Audio"
-#: models.py:432
+#: models.py:444
msgid "Video"
msgstr "Vidéo"
-#: models.py:434
+#: models.py:446
msgid "Other"
msgstr "Autre"
-#: models.py:435
+#: models.py:447
msgid "Media type"
msgstr "Type de media"
-#: models.py:438
+#: models.py:450
msgid "Mime type"
msgstr "Type mime"
-#: models.py:440
+#: models.py:452
msgid "Inside an iframe"
msgstr "À l'intérieur d'un iframe"
-#: models.py:444
+#: models.py:456
msgid "Multimedia type"
msgstr "Type de multimedia"
-#: models.py:445
+#: models.py:457
msgid "Multimedia types"
msgstr "Types de multimedia"
-#: models.py:481
+#: models.py:493
msgid "Url"
msgstr "Url"
-#: models.py:484 models.py:529
+#: models.py:496 models.py:541
msgid "Display inside the description?"
msgstr "Apparaît dans la description ?"
-#: models.py:489
+#: models.py:501
msgid "Multimedia file"
msgstr "Fichier multimedia"
-#: models.py:538
+#: models.py:550
msgid "Picture file"
msgstr "Fichier d'image"
-#: models.py:556
+#: models.py:568
msgid "Raw file (gpx or kml)"
msgstr "Fichier brut (gpx ou kml)"
-#: models.py:557
+#: models.py:569
msgid "Simplified file"
msgstr "Fichier simplifié"
-#: models.py:559
+#: models.py:571
msgid "KML"
msgstr "KML"
-#: models.py:559
+#: models.py:571
msgid "GPX"
msgstr "GPX"
-#: models.py:564
+#: models.py:576
msgid "Route file"
msgstr "Fichier de trajet"
-#: models.py:565
+#: models.py:577
msgid "Route files"
msgstr "Fichiers de trajet"
-#: models.py:615
+#: models.py:627
msgid "Reference route"
msgstr "Trajet de référence"
-#: models.py:619
+#: models.py:631
msgid "Associated file"
msgstr "Fichier associé"
-#: models.py:793
+#: models.py:805
msgid "Layer code"
msgstr "Code pour la couche"
-#: models.py:799
+#: models.py:811
msgid "Layer"
msgstr "Couche"
-#: models.py:805
+#: models.py:817
msgid "Area urn"
msgstr "Urn de la zone"
-#: models.py:807 templates/chimere/blocks/welcome.html:3
+#: models.py:819 templates/chimere/blocks/welcome.html:3
msgid "Welcome message"
msgstr "Message d'accueil"
-#: models.py:811
+#: models.py:823
msgid "Upper left corner"
msgstr "Coin en haut à gauche"
-#: models.py:813
+#: models.py:825
msgid "Lower right corner"
msgstr "Coin en bas à droite"
-#: models.py:815
+#: models.py:827
msgid "Default area"
msgstr "Zone par défaut"
-#: models.py:816
+#: models.py:828
msgid "Only one area is set by default"
msgstr "Seule une zone est définie par défaut"
-#: models.py:820
+#: models.py:832
msgid "Sub-categories checked by default"
msgstr "Sous-catégories cochées par défaut"
-#: models.py:822
+#: models.py:834
msgid "Sub-categories dynamicaly displayed"
msgstr "Sous-categories affichées dynamiquement"
-#: models.py:823
+#: models.py:835
msgid ""
"If checked, categories are only displayed in the menu if they are available "
"on the current extent."
@@ -473,57 +481,68 @@ msgstr ""
"Si coché, les catégories sont disponibles sur le menu seulement si elles "
"apparaissent sur la zone affichée."
-#: models.py:827
+#: models.py:839 models.py:906
msgid "Restricted to theses sub-categories"
msgstr "Restreindre à ces sous-categories"
-#: models.py:828
+#: models.py:840
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:830
+#: models.py:842
msgid "Link to an external CSS"
msgstr "Lien vers une feuille de style externe"
-#: models.py:832
+#: models.py:844
msgid "Restrict to the area extent"
msgstr "Restreindre à l'étendue de la zone"
-#: models.py:879
+#: models.py:891
msgid "Default layer"
msgstr "Couche par défaut"
-#: models.py:883 models.py:884
+#: models.py:895 models.py:896
msgid "Layers"
msgstr "Couches"
-#: models.py:892
+#: models.py:904
+msgid "Mandatory"
+msgstr "Obligatoire"
+
+#: models.py:907
+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:909
msgid "Text"
msgstr "Texte"
-#: models.py:893
+#: models.py:910
msgid "Long text"
msgstr "Texte long"
-#: models.py:894
+#: models.py:911
msgid "Password"
msgstr "Mot de passe"
-#: models.py:898
+#: models.py:917
msgid "Type"
msgstr "Type"
-#: models.py:903 models.py:915
+#: models.py:922 models.py:934
msgid "Property model"
msgstr "Modèle de propriété"
-#: models.py:916
+#: models.py:935
msgid "Value"
msgstr "Valeur"
-#: models.py:920
+#: models.py:939
msgid "Property"
msgstr "Propriété"
@@ -623,19 +642,19 @@ msgstr ""
msgid "Bad param"
msgstr "Mauvais paramètre"
-#: views.py:228
+#: views.py:236
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:307
+#: views.py:319
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:429
+#: views.py:441
msgid "Comments/request on the map"
msgstr "Commentaires/requètes sur la carte"
-#: views.py:432
+#: views.py:444
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."
@@ -644,15 +663,15 @@ msgstr ""
"laissé votre courriel vous serez peut-être contacté bientôt pour plus de "
"détails."
-#: views.py:436
+#: views.py:448
msgid "Temporary error. Renew your message later."
msgstr "Erreur temporaire. Réenvoyez votre message plus tard."
-#: views.py:567
+#: views.py:579
msgid "No category available in this area."
msgstr "Pas de catégorie disponible sur cette zone."
-#: views.py:696
+#: views.py:708
msgid "Incorrect choice in the list"
msgstr "Choix incorrect dans la liste"
@@ -807,8 +826,8 @@ msgid "Error"
msgstr "Erreur"
#: templates/chimere/edit.html:24
-msgid "Add/modify a site"
-msgstr "Ajouter ou modifier un site"
+msgid "Add/modify a point of interest"
+msgstr "Ajout d'un point d'intérêt"
#: templates/chimere/edit.html:30
msgid "Point"
@@ -826,7 +845,32 @@ msgstr "indique un champ obligatoire"
msgid "Categories"
msgstr "Catégories"
-#: templates/chimere/edit.html:86 templates/chimere/edit_route.html:77
+#: templates/chimere/edit.html:113
+msgid "Personal information"
+msgstr "Informations personnelles"
+
+#: templates/chimere/edit.html:115
+msgid ""
+"This fields are not mandatory. If you provided them they not will be made "
+"public and they will only used to join you for this project."
+msgstr ""
+"Ces champs ne sont pas obligatoires. Si vous les renseignez, ils ne seront "
+"pas publiés et ne seront utilisés seulement pour vous joindre dans le cadre "
+"de ce projet."
+
+#: templates/chimere/edit.html:118
+msgid "Your name or nickname"
+msgstr "Votre nom ou pseudo"
+
+#: templates/chimere/edit.html:123
+msgid "Your email"
+msgstr "Votre courriel"
+
+#: templates/chimere/edit.html:128
+msgid "Comments about your submission"
+msgstr "Commentaires au sujet de votre proposition"
+
+#: templates/chimere/edit.html:133 templates/chimere/edit_route.html:77
msgid "Propose"
msgstr "Proposez"
diff --git a/chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py b/chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py
new file mode 100644
index 0000000..9965ec1
--- /dev/null
+++ b/chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py
@@ -0,0 +1,224 @@
+# -*- 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 field 'Marker.submiter_name'
+ db.add_column('chimere_marker', 'submiter_name',
+ self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Route.submiter_name'
+ db.add_column('chimere_route', 'submiter_name',
+ self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'Marker.submiter_name'
+ db.delete_column('chimere_marker', 'submiter_name')
+
+ # Deleting field 'Route.submiter_name'
+ db.delete_column('chimere_route', 'submiter_name')
+
+
+ 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', [], {}),
+ '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'},
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ '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'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', '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'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ '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.CharField', [], {'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.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']"}),
+ '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'},
+ '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', [], {}),
+ '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'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {})
+ },
+ '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'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {}),
+ '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'}),
+ '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'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ '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.CharField', [], {'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': 'False'}),
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'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', [], {})
+ },
+ '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/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py b/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py
new file mode 100644
index 0000000..53ee3d4
--- /dev/null
+++ b/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py
@@ -0,0 +1,241 @@
+# -*- 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 field 'PropertyModel.mandatory'
+ db.add_column('chimere_propertymodel', 'mandatory',
+ self.gf('django.db.models.fields.BooleanField')(default=False),
+ keep_default=False)
+
+ # Adding M2M table for field subcategories on 'PropertyModel'
+ db.create_table('chimere_propertymodel_subcategories', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('propertymodel', models.ForeignKey(orm['chimere.propertymodel'], null=False)),
+ ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False))
+ ))
+ db.create_unique('chimere_propertymodel_subcategories', ['propertymodel_id', 'subcategory_id'])
+
+
+ # Changing field 'Marker.submiter_comment'
+ db.alter_column('chimere_marker', 'submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True))
+
+ # Changing field 'Route.submiter_comment'
+ db.alter_column('chimere_route', 'submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True))
+
+ def backwards(self, orm):
+ # Deleting field 'PropertyModel.mandatory'
+ db.delete_column('chimere_propertymodel', 'mandatory')
+
+ # Removing M2M table for field subcategories on 'PropertyModel'
+ db.delete_table('chimere_propertymodel_subcategories')
+
+
+ # Changing field 'Marker.submiter_comment'
+ db.alter_column('chimere_marker', 'submiter_comment', self.gf('django.db.models.fields.CharField')(max_length=200, null=True))
+
+ # Changing field 'Route.submiter_comment'
+ db.alter_column('chimere_route', 'submiter_comment', self.gf('django.db.models.fields.CharField')(max_length=200, null=True))
+
+ 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', [], {}),
+ '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'},
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ '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'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', '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'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ '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.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']"}),
+ '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'},
+ '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', [], {}),
+ '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'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {})
+ },
+ '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'}),
+ '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'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ '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': 'False'}),
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'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', [], {})
+ },
+ '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 2454c86..ca608e8 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -25,6 +25,7 @@ import simplejson as json
from lxml import etree
from datetime import datetime, timedelta
from subprocess import Popen, PIPE
+import unidecode
from django.conf import settings
from django.contrib.gis.db import models
@@ -38,7 +39,7 @@ from django import forms
from django.utils.translation import ugettext_lazy as _
from chimere.widgets import PointField, RouteField, SelectMultipleField, \
- TextareaWidget
+ TextareaWidget, DatePickerWidget
from chimere.managers import BaseGeoManager
from chimere.utils import KMLManager, OSMManager, ShapefileManager
@@ -233,9 +234,11 @@ class GeographicItem(models.Model):
categories = SelectMultipleField(SubCategory)
submiter_session_key = models.CharField(_(u"Submitter session key"),
blank=True, null=True, max_length=40)
+ submiter_name = models.CharField(_(u"Submitter name or nickname"),
+ blank=True, null=True, max_length=40)
submiter_email = models.EmailField(_(u"Submitter email"), blank=True,
null=True)
- submiter_comment = models.CharField(_(u"Submitter comment"), max_length=200,
+ submiter_comment = models.TextField(_(u"Submitter comment"), max_length=200,
blank=True, null=True)
STATUS = (('S', _(u'Submited')),
('A', _(u'Available')),
@@ -301,6 +304,15 @@ class Marker(GeographicItem):
def __unicode__(self):
return self.name
+ def __init__(self, *args, **kwargs):
+ super(Marker, self).__init__(*args, **kwargs)
+ # add read attributes for properties
+ for property in self.getProperties():
+ attr_name = unidecode.unidecode(property.propertymodel.name).lower()
+ attr_name = re.sub(r'\W+','_', attr_name.strip())
+ if not hasattr(self, attr_name):
+ setattr(self, attr_name, property.value)
+
def get_init_multi(self):
multis = [forms.model_to_dict(multi)
for multi in self.multimedia_files.all()]
@@ -889,12 +901,19 @@ class PropertyModel(models.Model):
name = models.CharField(_(u"Name"), max_length=150)
order = models.IntegerField(_(u"Order"))
available = models.BooleanField(_(u"Available"))
+ mandatory = models.BooleanField(_(u"Mandatory"))
+ subcategories = SelectMultipleField(SubCategory, related_name='properties',
+ blank=True, verbose_name=_(u"Restricted to theses sub-categories"),
+ help_text=_(u"If no sub-category is set all the property applies to all "
+ u"sub-categories"))
TYPE = (('T', _('Text')),
('L', _('Long text')),
- ('P', _('Password')))
+ ('P', _('Password')),
+ ('D', _("Date")))
TYPE_WIDGET = {'T':forms.TextInput,
'L':TextareaWidget,
- 'P':forms.PasswordInput}
+ 'P':forms.PasswordInput,
+ 'D':DatePickerWidget}
type = models.CharField(_(u"Type"), max_length=1, choices=TYPE)
def __unicode__(self):
return self.name
diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css
index e551ac6..ceb3b60 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -21,6 +21,7 @@ h2, h3, th, .action li, .action li a,
}
.action li.ui-state-active a,
+#content .olControlLayerSwitcher,
.action li li.ui-state-active a{
color:#333;
}
@@ -43,6 +44,8 @@ body, h2, h3, th,
fieldset, .action li, #content,
#map-footer, #panel, #chimere_itinerary_panel, #areas,
#welcome, #detail, .detail_footer a,
+#content .olControlLayerSwitcher .layersDiv,
+#content .olControlLayerSwitcher span,
#main-map, .window{
background-color:#FFF;
}
@@ -63,11 +66,13 @@ div.warning, .errorlist{
div.warning,
#content,
.action li.selected,
-#panel, #map-footer,
+#content .olControlLayerSwitcher .layersDiv,
+#panel, #map-footer, #chimere_itinerary_panel,
#utils-div{
border:1px solid #327e04;
}
+
.errorlist{
border:1px solid #ff3f3f;
}
@@ -705,10 +710,11 @@ table.inline-table td input[type=file]{
}
#content .olControlLayerSwitcher {
- top: 150px !important;
- right: auto !important;
- bottom: auto !important;
- left: 0 !important;
+ top: 250px !important;
+ right: auto !important;
+ bottom: auto !important;
+ left: 0 !important;
+ font-weight:normal;
}
@@ -809,3 +815,84 @@ html > body .media-state {
.jme-flashbutton-wrapper .media-controls > *:not(.fullscreen) {
pointer-events: auto;
}
+
+/*
+ SimplePanZoom
+*/
+
+.olControlSimplePanZoom {
+ top: 10px;
+ right: 10px;
+}
+
+.olControlSimplePanZoom .button {
+ background-image: url('../img/map_sprite.png');
+ position:absolute;
+ background-repeat: no-repeat;
+ cursor:hand;
+ cursor:pointer;
+}
+
+.olControlSimplePanZoom #panup {
+ left:10px;
+ width:25px;
+ height:13px;
+ background-position: -15px -5px;
+}
+
+.olControlSimplePanZoom #pandown {
+ left:10px;
+ top:36px;
+ width:25px;
+ height:15px;
+ background-position: -15px -40px;
+}
+
+.olControlSimplePanZoom #panleft {
+ top:13px;
+ width:25px;
+ height:23px;
+ background-position: -5px -17px;
+}
+
+.olControlSimplePanZoom #panright {
+ top:13px;
+ width:25px;
+ height:23px;
+ left:25px;
+ background-position: -30px -17px;
+}
+
+.olControlSimplePanZoom #zoomin {
+ top:50px;
+ width:25px;
+ height:20px;
+ left:10px;
+ background-position: -15px -61px;
+}
+
+.olControlSimplePanZoom #zoomout {
+ top:210px;
+ width:25px;
+ height:20px;
+ left:10px;
+ background-position: -15px -220px;
+}
+
+.olControlSimplePanZoom #slider {
+ top:75px;
+ width:25px;
+ height:10px;
+ left:10px;
+ -webkit-transition:top 100ms linear;
+ background-position: -77px -58px;
+ pointer:move;
+ cursor:move;
+}
+.olControlSimplePanZoom #zoombar {
+ top:70px;
+ width:25px;
+ height:140px;
+ left:10px;
+ background-position: -15px -80px;
+}
diff --git a/chimere/static/chimere/img/layer-switcher-maximize.png b/chimere/static/chimere/img/layer-switcher-maximize.png
index 8b1e686..80dd651 100644
--- a/chimere/static/chimere/img/layer-switcher-maximize.png
+++ b/chimere/static/chimere/img/layer-switcher-maximize.png
Binary files differ
diff --git a/chimere/static/chimere/img/layer-switcher-minimize.png b/chimere/static/chimere/img/layer-switcher-minimize.png
index e80bf21..9321717 100644
--- a/chimere/static/chimere/img/layer-switcher-minimize.png
+++ b/chimere/static/chimere/img/layer-switcher-minimize.png
Binary files differ
diff --git a/chimere/static/chimere/img/map_sprite.png b/chimere/static/chimere/img/map_sprite.png
new file mode 100644
index 0000000..0635a41
--- /dev/null
+++ b/chimere/static/chimere/img/map_sprite.png
Binary files differ
diff --git a/chimere/static/chimere/js/SimplePanZoom.js b/chimere/static/chimere/js/SimplePanZoom.js
new file mode 100644
index 0000000..e42dc54
--- /dev/null
+++ b/chimere/static/chimere/js/SimplePanZoom.js
@@ -0,0 +1,362 @@
+/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control/PanZoom.js
+ */
+
+/**
+ * Class: OpenLayers.Control.PanZoomBar
+ * The PanZoomBar is a visible control composed of a
+ * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>.
+ * By default it is displayed in the upper left corner of the map as 4
+ * directional arrows above a vertical slider.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control.PanZoom>
+ */
+OpenLayers.Control.SimplePanZoom = OpenLayers.Class(OpenLayers.Control.PanZoom, {
+
+ /**
+ * APIProperty: zoomStopWidth
+ */
+ zoomStopWidth: 18,
+
+ /**
+ * APIProperty: zoomStopHeight
+ */
+ zoomStopHeight: 7,
+
+ /**
+ * Property: slider
+ */
+ slider: null,
+
+ /**
+ * Property: sliderEvents
+ * {<OpenLayers.Events>}
+ */
+ sliderEvents: null,
+
+ /**
+ * Property: zoombarDiv
+ * {DOMElement}
+ */
+ zoombarDiv: null,
+
+ /**
+ * APIProperty: zoomWorldIcon
+ * {Boolean}
+ */
+ zoomWorldIcon: false,
+
+ /**
+ * APIProperty: panIcons
+ * {Boolean} Set this property to false not to display the pan icons. If
+ * false the zoom world icon is placed under the zoom bar. Defaults to
+ * true.
+ */
+ panIcons: true,
+
+ /**
+ * APIProperty: forceFixedZoomLevel
+ * {Boolean} Force a fixed zoom level even though the map has
+ * fractionalZoom
+ */
+ forceFixedZoomLevel: false,
+
+ /**
+ * Property: mouseDragStart
+ * {<OpenLayers.Pixel>}
+ */
+ mouseDragStart: null,
+
+ /**
+ * Property: deltaY
+ * {Number} The cumulative vertical pixel offset during a zoom bar drag.
+ */
+ deltaY: null,
+
+ /**
+ * Property: zoomStart
+ * {<OpenLayers.Pixel>}
+ */
+ zoomStart: null,
+
+ /**
+ * Constructor: OpenLayers.Control.PanZoomBar
+ */
+ buttons: null,
+
+ /**
+ * APIMethod: destroy
+ */
+ destroy: function() {
+
+ this._removeZoomBar();
+
+ this.map.events.un({
+ "changebaselayer": this.redraw,
+ "updatesize": this.redraw,
+ scope: this
+ });
+
+ OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
+
+ delete this.mouseDragStart;
+ delete this.zoomStart;
+ },
+
+ /**
+ * Method: setMap
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
+ this.map.events.on({
+ "changebaselayer": this.redraw,
+ "updatesize": this.redraw,
+ scope: this
+ });
+ },
+
+ /**
+ * Method: redraw
+ * clear the div and start over.
+ */
+ redraw: function() {
+ if (this.div !== null) {
+ this.removeButtons();
+ this._removeZoomBar();
+ }
+ this.draw();
+ },
+
+ /**
+ * Method: draw
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>}
+ */
+ draw: function(px) {
+ // initialize our internal div
+ OpenLayers.Control.prototype.draw.apply(this, arguments);
+ px = this.position.clone();
+
+ // place the controls
+ this.buttons = [];
+ var ids = ['panup', 'panleft', 'panright', 'pandown', 'zoomout', 'zoomin'];
+
+ for (var i = 0; i < ids.length; i++) {
+ var b = document.createElement('div');
+ b.id = ids[i];
+ b.action = ids[i];
+ b.className = 'button olButton';
+ this.div.appendChild(b);
+ this.buttons.push(b);
+ }
+
+ this._addZoomBar();
+ return this.div;
+ },
+
+ /**
+ * Method: _addZoomBar
+ *
+ * Parameters:
+ * centered - {<OpenLayers.Pixel>} where zoombar drawing is to start.
+ */
+ _addZoomBar:function() {
+ var id = this.id + "_" + this.map.id;
+ var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
+ var slider = document.createElement('div');
+ slider.id = 'slider';
+ slider.className = 'button';
+ slider.style.cursor = 'move';
+ this.slider = slider;
+
+ this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
+ { includeXY: true });
+ this.sliderEvents.on({
+ "touchstart": this.zoomBarDown,
+ "touchmove": this.zoomBarDrag,
+ "touchend": this.zoomBarUp,
+ "mousedown": this.zoomBarDown,
+ "mousemove": this.zoomBarDrag,
+ "mouseup": this.zoomBarUp
+ });
+
+ var height = this.zoomStopHeight * (this.map.getNumZoomLevels());
+
+ // this is the background image
+ var div = document.createElement('div');
+ div.className = 'button';
+ div.id = 'zoombar';
+ this.zoombarDiv = div;
+
+ this.div.appendChild(div);
+ this.startTop = 75;
+ this.div.appendChild(slider);
+
+ this.map.events.register("zoomend", this, this.moveZoomBar);
+ },
+
+ /**
+ * Method: _removeZoomBar
+ */
+ _removeZoomBar: function() {
+ this.sliderEvents.un({
+ "touchstart": this.zoomBarDown,
+ "touchmove": this.zoomBarDrag,
+ "touchend": this.zoomBarUp,
+ "mousedown": this.zoomBarDown,
+ "mousemove": this.zoomBarDrag,
+ "mouseup": this.zoomBarUp
+ });
+ this.sliderEvents.destroy();
+
+ this.div.removeChild(this.zoombarDiv);
+ this.zoombarDiv = null;
+ this.div.removeChild(this.slider);
+ this.slider = null;
+
+ this.map.events.unregister("zoomend", this, this.moveZoomBar);
+ },
+
+ /**
+ * Method: onButtonClick
+ *
+ * Parameters:
+ * evt - {Event}
+ */
+ onButtonClick: function(evt) {
+ OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this, arguments);
+ if (evt.buttonElement === this.zoombarDiv) {
+ var levels = evt.buttonXY.y / this.zoomStopHeight;
+ if (this.forceFixedZoomLevel || !this.map.fractionalZoom) {
+ levels = Math.floor(levels);
+ }
+ var zoom = (this.map.getNumZoomLevels() - 1) - levels;
+ zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
+ this.map.zoomTo(zoom);
+ }
+ },
+
+ /**
+ * Method: passEventToSlider
+ * This function is used to pass events that happen on the div, or the map,
+ * through to the slider, which then does its moving thing.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ passEventToSlider:function(evt) {
+ this.sliderEvents.handleBrowserEvent(evt);
+ },
+
+ /*
+ * Method: zoomBarDown
+ * event listener for clicks on the slider
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ zoomBarDown:function(evt) {
+ if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
+ return;
+ }
+ this.map.events.on({
+ "touchmove": this.passEventToSlider,
+ "mousemove": this.passEventToSlider,
+ "mouseup": this.passEventToSlider,
+ scope: this
+ });
+ this.mouseDragStart = evt.xy.clone();
+ this.zoomStart = evt.xy.clone();
+ this.div.style.cursor = "move";
+ // reset the div offsets just in case the div moved
+ this.zoombarDiv.offsets = null;
+ OpenLayers.Event.stop(evt);
+ },
+
+ /*
+ * Method: zoomBarDrag
+ * This is what happens when a click has occurred, and the client is
+ * dragging. Here we must ensure that the slider doesn't go beyond the
+ * bottom/top of the zoombar div, as well as moving the slider to its new
+ * visual location
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ zoomBarDrag: function(evt) {
+ if (this.mouseDragStart !== null) {
+ var deltaY = this.mouseDragStart.y - evt.xy.y;
+ var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
+ if ((evt.clientY - offsets[1]) > 0 &&
+ (evt.clientY - offsets[1]) < 140) {
+ var newTop = parseInt(this.slider.style.top, 10) - deltaY;
+ this.slider.style.top = newTop + "px";
+ this.mouseDragStart = evt.xy.clone();
+ }
+ // set cumulative displacement
+ this.deltaY = this.zoomStart.y - evt.xy.y;
+ OpenLayers.Event.stop(evt);
+ }
+ },
+
+ /*
+ * Method: zoomBarUp
+ * Perform cleanup when a mouseup event is received -- discover new zoom
+ * level and switch to it.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ zoomBarUp: function(evt) {
+ if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
+ return;
+ }
+ if (this.mouseDragStart) {
+ this.div.style.cursor="";
+ this.map.events.un({
+ "touchmove": this.passEventToSlider,
+ "mouseup": this.passEventToSlider,
+ "mousemove": this.passEventToSlider,
+ scope: this
+ });
+ var zoomLevel = this.map.zoom;
+ if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
+ zoomLevel += this.deltaY/this.zoomStopHeight;
+ zoomLevel = Math.min(Math.max(zoomLevel, 0),
+ this.map.getNumZoomLevels() - 1);
+ } else {
+ zoomLevel += this.deltaY/this.zoomStopHeight;
+ zoomLevel = Math.max(Math.round(zoomLevel), 0);
+ }
+ this.map.zoomTo(zoomLevel);
+ this.mouseDragStart = null;
+ this.zoomStart = null;
+ this.deltaY = 0;
+ OpenLayers.Event.stop(evt);
+ }
+ },
+
+ /*
+ * Method: moveZoomBar
+ * Change the location of the slider to match the current zoom level.
+ */
+ moveZoomBar:function() {
+ var newTop =
+ ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) *
+ this.zoomStopHeight + this.startTop;
+ this.slider.style.top = newTop + "px";
+ },
+
+ CLASS_NAME: "OpenLayers.Control.SimplePanZoom"
+});
diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js
index f46f3eb..ff90f28 100644
--- a/chimere/static/chimere/js/jquery.chimere.js
+++ b/chimere/static/chimere/js/jquery.chimere.js
@@ -16,6 +16,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
See the file COPYING for details.
*/
+/* Add OpenLayers MapQuest layer management */
+OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+ name: "MapQuestOSM",
+ sphericalMercator: true,
+ url: ' http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png',
+ clone: function(obj) {
+ if (obj == null) {
+ obj = new OpenLayers.Layer.OSM(
+ this.name, this.url, this.getOptions());
+ }
+ obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+ return obj;
+ },
+ CLASS_NAME: "OpenLayers.Layer.MapQuestOSM"
+});
+
/*
* Little hasattr helper
*/
@@ -59,8 +75,7 @@ See the file COPYING for details.
get_subcategories_fx: null,
hide_popup_fx: null,
controls:[new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanPanel(),
- new OpenLayers.Control.ZoomPanel(),
+ new OpenLayers.Control.SimplePanZoom(),
new OpenLayers.Control.ScaleLine()],
maxResolution: 156543.0399,
units: 'm',
diff --git a/chimere/templates/chimere/edit.html b/chimere/templates/chimere/edit.html
index 5170798..447de71 100644
--- a/chimere/templates/chimere/edit.html
+++ b/chimere/templates/chimere/edit.html
@@ -21,7 +21,7 @@
<p>{{ error_message }}</p>
{% endif %}</fieldset>
<fieldset class='edit'>
- <legend>{% trans "Add/modify a site" %}</legend>
+ <legend>{% trans "Add/modify a point of interest" %}</legend>
<form enctype="multipart/form-data" method='post' action='.'>
{% csrf_token %}
<div class='rightWrapper'>
@@ -69,10 +69,9 @@
<div class='bottomform'>
{% for field in form %}
{% for property in properties %}
- {% ifequal field.name property %}
+ {% ifequal field.name property.getNamedId %}
<div class="fieldWrapper">
- <label for="id_{{field.name}}">{% trans field.label %}</label>
- {{ field.errors }}
+ <label for="id_{{field.name}}">{% trans field.label %}{% if property.mandatory %} *{% endif %}</label>
{% if field.errors %}<div class='errors'>{{ field.errors }}</div>{% endif %}
{{ field }}
</div>
@@ -83,8 +82,55 @@
{% inline_formset "Multimedia files" formset_multi %}
{% inline_formset "Picture files" formset_picture %}
- <p><input type='submit' onclick='saveExtent();' value="{% trans 'Propose'%}"/></p>
+ {% if filtered_properties %}
+ <script type='text/javascript'>
+ var cat_filters = new Array();
+ var cat_to_hide = new Array();
+ {% for property in filtered_properties %}
+ cat_to_hide.push('#id_{{property.getNamedId}}');
+ {% for subcat in property.subcategories.all %}
+ if(!cat_filters['{{subcat.id}}']) cat_filters['{{subcat.id}}'] = new Array();
+ cat_filters['{{subcat.id}}'].push('#id_{{property.getNamedId}}');
+ {% endfor %}
+ {% endfor %}
+ $('#id_categories').change(function(){
+ for (idx in cat_to_hide){
+ $(cat_to_hide[idx]).parent().hide();
+ }
+ var vals = $(this).val();
+ for (val_id in vals){
+ var val = vals[val_id];
+ for (ids in cat_filters[val]){
+ $(cat_filters[val][ids]).parent().show();
+ }
+ }
+ });
+ $('#id_categories').change();
+ </script>
+ {% endif %}
+ </div>
+ <div class='personalform'>
+ <h3>{% trans "Personal information"%}</h3>
+ <div class='warning'>
+ {% trans "This fields are not mandatory. If you provided them they not will be made public and they will only used to join you for this project."%}
+ </div>
+ <div class="fieldWrapper">
+ <label for="id_submiter_name">{% trans "Your name or nickname"%}</label>
+ {% if form.submiter_name.errors %}<div class='errors'>{{ form.submiter_name.errors }}</div>{% endif %}
+ {{ form.submiter_name }}
+ </div>
+ <div class="fieldWrapper">
+ <label for="id_submiter_email">{% trans "Your email"%}</label>
+ {% if form.submiter_email.errors %}<div class='errors'>{{ form.submiter_email.errors }}</div>{% endif %}
+ {{ form.submiter_email }}
+ </div>
+ <div class="fieldWrapper">
+ <label for="id_submiter_comment">{% trans "Comments about your submission"%}</label>
+ {% if form.submiter_comment.errors %}<div class='errors'>{{ form.submiter_comment.errors }}</div>{% endif %}
+ {{ form.submiter_comment }}
+ </div>
</div>
+ <p><input type='submit' onclick='saveExtent();' value="{% trans 'Propose'%}"/></p>
</form>
</fieldset>
</div>
diff --git a/chimere/views.py b/chimere/views.py
index bd1f441..dd3f89a 100644
--- a/chimere/views.py
+++ b/chimere/views.py
@@ -139,7 +139,9 @@ def index(request, area_name=None, default_area=None, simple=False):
return render_to_response(tpl, response_dct,
context_instance=RequestContext(request))
-def get_edit_page(redirect_url, item_cls, item_form):
+def get_edit_page(redirect_url, item_cls, item_form,
+ multimediafile_formset=MultimediaFileFormSet,
+ picturefile_formset=PictureFileFormSet):
"""
Edition page
"""
@@ -171,6 +173,12 @@ def get_edit_page(redirect_url, item_cls, item_form):
init_multi = init_item.get_init_multi() if init_item else None
init_picture = init_item.get_init_picture() if init_item else None
+ if init_item and not request.user.is_superuser and \
+ not init_item.submiter_session_key == \
+ request.session.session_key:
+ # hide personal information
+ for k in ('submiter_name', 'submiter_email', 'submiter_comment'):
+ setattr(init_item, k, '')
# If the form has been submited
if request.method == 'POST':
inst = None
@@ -182,9 +190,9 @@ def get_edit_page(redirect_url, item_cls, item_form):
form = item_form(request.POST, request.FILES, instance=inst,
subcategories=listed_subcats)
- formset_multi = MultimediaFileFormSet(request.POST, request.FILES,
+ formset_multi = multimediafile_formset(request.POST, request.FILES,
initial=init_multi, prefix='multimedia')
- formset_picture = PictureFileFormSet(request.POST, request.FILES,
+ formset_picture = picturefile_formset(request.POST, request.FILES,
initial=init_picture, prefix='picture')
# All validation rules pass
if form.is_valid() and formset_multi.is_valid() and \
@@ -229,9 +237,9 @@ def get_edit_page(redirect_url, item_cls, item_form):
u" and/or errors in the submited form.")
else:
form = item_form(instance=init_item, subcategories=listed_subcats)
- formset_multi = MultimediaFileFormSet(initial=init_multi,
+ formset_multi = multimediafile_formset(initial=init_multi,
prefix='multimedia')
- formset_picture = PictureFileFormSet(initial=init_picture,
+ formset_picture = picturefile_formset(initial=init_picture,
prefix='picture')
return None, (item_id, init_item, response_dct, form, formset_multi,
formset_picture), subcategories
@@ -252,6 +260,9 @@ def edit(request, area_name="", item_id=None, submited=False):
# get the "manualy" declared_fields. Ie: properties
declared_fields = form.declared_fields.keys()
+ declared_fields = PropertyModel.objects.filter(available=True).all()
+ filtered_properties = PropertyModel.objects.filter(available=True,
+ subcategories__id__isnull=False).all()
response_dct.update({
'actions':actions,
'action_selected':('contribute', 'edit'),
@@ -267,6 +278,7 @@ def edit(request, area_name="", item_id=None, submited=False):
init_item.point if init_item else None,
area_name=response_dct['area_name']),
'properties':declared_fields,
+ 'filtered_properties':filtered_properties,
'submited':submited
})
# manualy populate the custom widget
diff --git a/chimere/widgets.py b/chimere/widgets.py
index f5617de..b520fcd 100644
--- a/chimere/widgets.py
+++ b/chimere/widgets.py
@@ -155,7 +155,7 @@ class DatePickerWidget(forms.TextInput):
def render(self, *args, **kwargs):
rendered = super(DatePickerWidget, self).render(*args, **kwargs)
rendered += u"\n<script type='text/javascript'>\n"\
- u" $('#%s').datepicker({ dateFormat: 'yy-mm-dd' });\n"\
+ u" $(function() {$('#%s').datepicker({ dateFormat: 'yy-mm-dd' });});\n"\
u"</script>\n" % kwargs['attrs']['id']
return mark_safe(rendered)
diff --git a/debian/control b/debian/control
index 7317430..92cfa21 100644
--- a/debian/control
+++ b/debian/control
@@ -4,6 +4,7 @@ Depends: python-django (>=1.3), python-gdal, python-psycopg2,
python-beautifulsoup, python-imaging, libjs-jquery,
libjs-jquery-ui, libjs-jquery-ui-theme-base,
postgresql-9.1, postgresql-9.1-postgis, gettext,
- python-simplejson, gpsbabel, python-django-south
+ python-simplejson, gpsbabel, python-django-south,
+ python-unidecode
Recommends: tinymce, python-django-celery, python-kombu
Suggests: libjs-jquery-ui-theme-south-street
diff --git a/docs/install.rst b/docs/install.rst
index 2f66879..d0f918a 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -32,6 +32,7 @@ Prerequisites
- `Beautiful Soup <http://www.crummy.com/software/BeautifulSoup/>`_
- python-simplejson
- python-gdal
+ - `unidecode <http://pypi.python.org/pypi/Unidecode>_
- `lxml <http://lxml.de/>`_
- `jquery <http://jquery.com/>`_ version 1.7.1 or better
- `jquery-ui <http://jqueryui.com/>`_
@@ -59,7 +60,8 @@ Linux distribution repositories. For instance on Debian Wheezy::
python-beautifulsoup tinymce apache2 libgeos-3.3.3 proj-bin gdal-bin \
python-gdal python-lxml python-psycopg2 python-imaging gettext \
postgresql-9.1 postgresql-9.1-postgis libjs-jquery libjs-jquery-ui \
- python-django-celery python-simplejson python-gdal gpsbabel
+ python-django-celery python-simplejson python-gdal python-unidecode \
+ gpsbabel
If these packages do not exist in your distribution's repository, please refer
to the applications' websites.
diff --git a/docs/upgrade.rst b/docs/upgrade.rst
index 9f36eb4..aca3985 100644
--- a/docs/upgrade.rst
+++ b/docs/upgrade.rst
@@ -44,14 +44,15 @@ Activate the backports: http://backports-master.debian.org/Instructions/
Then install the new dependencies::
apt-get install -t squeeze-backports python-django python-django-south \
- python-simplejson libjs-jquery-ui
+ python-simplejson libjs-jquery-ui python-unidecode
Debian Wheezy
+++++++++++++
.. code-block:: bash
- apt-get install python-django-south python-simplejson libjs-jquery-ui
+ apt-get install python-django-south python-simplejson libjs-jquery-ui \
+ python-unidecode
If you are planing to do major import consider the install of `Celery
<http://celeryproject.org/>`_.
diff --git a/example_project/settings.py b/example_project/settings.py
index 46b8e95..750d798 100644
--- a/example_project/settings.py
+++ b/example_project/settings.py
@@ -26,6 +26,7 @@ JQUERY_CSS_URLS = ('/javascript/jquery-ui/css/smoothness/jquery-ui.css',
OSM_CSS_URLS = ["http://www.openlayers.org/api/theme/default/style.css"]
OSM_JS_URLS = [STATIC_URL + "chimere/js/OpenLayers.js",
+ STATIC_URL + "chimere/js/SimplePanZoom.js",
"http://www.openstreetmap.org/openlayers/OpenStreetMap.js"]
GPSBABEL = '/usr/bin/gpsbabel'
diff --git a/requirements.txt b/requirements.txt
index e1f2c46..843a351 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ pil
lxml
south==0.7.3
simplejson
+unidecode