diff options
Diffstat (limited to 'chimere')
105 files changed, 4937 insertions, 667 deletions
diff --git a/chimere/actions.py b/chimere/actions.py index 0363d54..8ef5338 100644 --- a/chimere/actions.py +++ b/chimere/actions.py @@ -22,21 +22,44 @@ Actions available in the main interface """ from django.conf import settings from django.contrib.auth import models +from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ +from models import Page + class Action: - def __init__(self, id, path, label): + def __init__(self, id, path, label, extra_url_args=[]): self.id, self.path, self.label = id, path, label + self.extra_url_args, self.url = extra_url_args, None + + def update_url(self, area_name): + self.url = reverse(self.path, + args=[area_name + '/' if area_name else ''] + self.extra_url_args) -actions = [(Action('view', '', _('View')), []), - (Action('contribute', 'edit/', _('Contribute')), - (Action('edit', 'edit/', _('Add a new point of interest')), - Action('edit-route', 'edit-route/', _('Add a new route'))), - ),] +default_actions = [(Action('view', 'chimere:index', _('View')), []), + (Action('contribute', 'chimere:edit', _('Contribute')), + (Action('edit', 'chimere:edit', _('Add a new point of interest')), + Action('edit-route', 'chimere:editroute', _('Add a new route'))), + ),] if settings.CHIMERE_FEEDS: - actions.append((Action('rss', 'feeds', _('RSS feeds')), [])) + default_actions.append((Action('rss', 'chimere:feeds-form', + _('RSS feeds')), [])) if settings.EMAIL_HOST: - actions.append((Action('contact', 'contact', _('Contact us')), []),) + default_actions.append((Action('contact', 'chimere:contact', + _('Contact us')), []),) + +def actions(area_name=''): + acts = default_actions[:] + for act, childs in default_actions: + act.update_url(area_name) + for child_act in childs: + child_act.update_url(area_name) + for page in Page.objects.filter(available=True).order_by('order'): + act = Action(page.mnemonic, 'chimere:extra_page', page.title, + [page.mnemonic]) + act.update_url(area_name) + acts.append((act, [])) + return acts diff --git a/chimere/admin.py b/chimere/admin.py index 6c7b2cc..c9107a5 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -37,15 +37,15 @@ except ImportError: pass from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ - NewsAdminForm, CategoryAdminForm, ImporterAdminForm, \ - PictureFileAdminForm, MultimediaFileAdminForm, OSMForm + NewsAdminForm, CategoryAdminForm, ImporterAdminForm, OSMForm, \ + PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm from chimere.models import Category, Icon, SubCategory, Marker, \ PropertyModel, News, Route, Area, ColorTheme, Color, \ MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ + PropertyModelChoice, MultimediaExtension, Page,\ get_areas_for_user, get_users_by_area from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\ CSVManager -from chimere.widgets import TextareaWidget def disable(modeladmin, request, queryset): for item in queryset: @@ -186,9 +186,9 @@ class MarkerAdmin(admin.ModelAdmin): actions = [validate, disable, managed_modified, export_to_kml, export_to_shapefile, export_to_csv] exclude = ['submiter_session_key', 'import_key', 'import_version', - 'available_date'] + 'available_date', 'ref_item'] readonly_fields = ['submiter_email', 'submiter_comment', 'import_source', - 'ref_item', 'modified_since_import', 'route'] + 'submiter_name', 'ref_item', 'modified_since_import', 'route'] form = MarkerAdminForm fieldsets = ((None, { 'fields': ['point', 'name', 'status', 'categories', @@ -387,11 +387,17 @@ class ImporterAdmin(admin.ModelAdmin): form = ImporterAdminForm list_display = ('display_categories', 'default_name', 'importer_type', 'source', 'state', 'filtr') - list_filter = ('importer_type',) + list_filter = ('importer_type', 'categories') readonly_fields = ('state',) actions = [importing, cancel_import, export_to_osm, cancel_export] admin.site.register(Importer, ImporterAdmin) +class PageAdmin(admin.ModelAdmin): + """ + Use the TinyMCE widget for the page content + """ + form = PageAdminForm + class PropertyModelAdmin(admin.ModelAdmin): list_display = ('name', 'order', 'available') @@ -421,8 +427,16 @@ class ColorThemeAdmin(admin.ModelAdmin): class IconAdmin(admin.ModelAdmin): exclude = ['height', 'width'] + list_display = ['name'] + +class PropertyModelChoiceInline(admin.TabularInline): + model = PropertyModelChoice + extra = 1 +class PropertyModelAdmin(admin.ModelAdmin): + inlines = [PropertyModelChoiceInline] # register of differents database fields +admin.site.register(Page, PageAdmin) admin.site.register(News, NewsAdmin) admin.site.register(Category, CategoryAdmin) admin.site.register(Icon, IconAdmin) diff --git a/chimere/forms.py b/chimere/forms.py index 774f510..655bbd3 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -33,10 +33,11 @@ from django.core.mail import EmailMessage, BadHeaderError from chimere.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ - PictureFile, Importer, IMPORTER_CHOICES, IFRAME_LINKS, MultimediaExtension + PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, \ + MultimediaExtension, Page, IMPORTER_CHOICES from chimere.widgets import AreaField, PointField, TextareaWidget, \ - ImportFiltrWidget, TextareaAdminWidget, DatePickerWidget, \ - ImporterChoicesWidget, RE_XAPI + FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget, \ + TextareaAdminWidget, ImportFiltrWidget, ImporterChoicesWidget, RE_XAPI from datetime import timedelta, datetime, tzinfo @@ -54,13 +55,18 @@ class UTC(tzinfo): def dst(self, dt): return ZERO +def getStaffEmails(): + return [u.email for u in + User.objects.filter(is_staff=True).exclude(email="").order_by('id')] + def notifyStaff(subject, body, sender=None): if not settings.EMAIL_HOST: return + user_list = getStaffEmails() + if not user_list: + return if settings.PROJECT_NAME: subject = u'[%s] %s' % (settings.PROJECT_NAME, subject) - user_list = [u.email for u in - User.objects.filter(is_staff=True).exclude(email="").order_by('id')] headers = {} if sender: headers['Reply-To'] = sender @@ -90,6 +96,20 @@ class ContactForm(forms.Form): email = forms.EmailField(label=_("Email (optional)"), required=False) content = forms.CharField(label=_("Object"), widget=forms.Textarea) +class SubCategoryAdminForm(forms.ModelForm): + ''' + Add a tinyMCE widget to fill description + ''' + description = forms.CharField(widget=FullTextareaWidget, required=False) + +class PageAdminForm(forms.ModelForm): + """ + Main form for extra pages + """ + content = forms.CharField(widget=FullTextareaWidget) + class Meta: + model = Page + class OSMForm(forms.Form): """ OSM export form @@ -165,6 +185,9 @@ class CategoryAdminForm(forms.ModelForm): js = list(settings.JQUERY_JS_URLS) + [ '%schimere/js/menu-sort.js' % settings.STATIC_URL, ] + css = { + 'all': ('chimere/css/admin.css',) + } class Meta: model = Category @@ -248,16 +271,32 @@ class MarkerAdminFormBase(forms.ModelForm): return new_marker # As we have dynamic fields, it's cleaner to make the class dynamic too -fields = {} -# declare properties -for prop in PropertyModel.objects.filter(available=True): - key = "property_%d_%d" % (prop.order, prop.id) - fields[key] = forms.CharField(label=prop.name, - widget=PropertyModel.TYPE_WIDGET[prop.type], - required=False) -MarkerAdminForm = type("MarkerAdminForm", (MarkerAdminFormBase,), fields) - -class MarkerForm(MarkerAdminForm): +def get_properties(queryset): + fields = {} + for prop in queryset: + key = "property_%d_%d" % (prop.order, prop.id) + if prop.type == 'C': + choices = PropertyModelChoice.objects.filter(propertymodel=prop, + available=True + ).order_by('value') + fields[key] = forms.ChoiceField(label=prop.name, + choices=[('', '--')] + \ + [(choice.pk, unicode(choice)) + for choice in choices], + required=False) + else: + fields[key] = forms.CharField(label=prop.name, + widget=PropertyModel.TYPE_WIDGET[prop.type], + required=False) + return fields + +# in admin all fields are displayed +MarkerAdminForm = type("MarkerAdminForm", (MarkerAdminFormBase,), + get_properties(PropertyModel.objects.all())) +MarkerBaseForm = type("MarkerBaseForm", (MarkerAdminFormBase,), + get_properties(PropertyModel.objects.filter(available=True))) + +class MarkerForm(MarkerBaseForm): """ Form for the edit page """ @@ -564,3 +603,30 @@ class AreaForm(AreaAdminForm): class Meta: model = Area +CHIMERE_ROUTING_TRANSPORT = [] +ROUTING_INIT = None +if hasattr(settings, 'CHIMERE_ROUTING_TRANSPORT'): + CHIMERE_ROUTING_TRANSPORT = [(idx, _(lbl)) + for idx, lbl in settings.CHIMERE_ROUTING_TRANSPORT] + if CHIMERE_ROUTING_TRANSPORT: + ROUTING_INIT = CHIMERE_ROUTING_TRANSPORT[0][0] + + +class RoutingForm(forms.Form): + transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, + choices=CHIMERE_ROUTING_TRANSPORT, + initial=ROUTING_INIT) + start = forms.CharField(label=_(u"Start"), widget=NominatimWidget) + end = forms.CharField(label=_(u"Finish"), widget=NominatimWidget) + speed = forms.ChoiceField(label=_(u"Speed"), choices=[], + required=False, widget=forms.RadioSelect) + + def __init__(self, *args, **kwargs): + super(RoutingForm, self).__init__(*args, **kwargs) + if not settings.CHIMERE_ROUTING_SPEEDS: + self.fields.pop('speed') + self.fields['speed'].widget.choices = [] + for transport in settings.CHIMERE_ROUTING_SPEEDS: + for speed, lbl in settings.CHIMERE_ROUTING_SPEEDS[transport]: + self.fields['speed'].widget.choices.append( + ("%s_%d" % (transport, speed), _(lbl))) diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index b2fc81c..f0b15b1 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,34 +7,34 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-02-01 13:13+0100\n" +"POT-Creation-Date: 2013-03-14 18:43+0100\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" -#: actions.py:31 +#: actions.py:39 msgid "View" msgstr "Voir" -#: actions.py:32 +#: actions.py:40 msgid "Contribute" msgstr "Participer" -#: actions.py:33 +#: actions.py:41 msgid "Add a new point of interest" msgstr "Ajout d'un point remarquable" -#: actions.py:34 +#: actions.py:42 msgid "Add a new route" msgstr "Ajout d'un nouveau trajet" -#: actions.py:38 +#: actions.py:47 msgid "RSS feeds" msgstr "Flux RSS" -#: actions.py:41 +#: actions.py:51 msgid "Contact us" msgstr "Nous contacter" @@ -75,57 +75,57 @@ msgstr "Élément modifié traité." msgid "Managed modified items" msgstr "Gérer les éléments modifiés" -#: admin.py:197 admin.py:272 +#: admin.py:197 admin.py:274 msgid "Submitter" msgstr "Demandeur" -#: admin.py:202 admin.py:277 admin.py:328 +#: admin.py:202 admin.py:279 admin.py:331 msgid "Import" msgstr "Import" -#: admin.py:207 admin.py:282 +#: admin.py:207 admin.py:284 msgid "Associated items" msgstr "Éléments associés" -#: admin.py:334 +#: admin.py:337 msgid "Cancel import" msgstr "Annuler l'import" -#: admin.py:340 +#: admin.py:343 msgid "Cancel export" msgstr "Annuler l'export" -#: admin.py:344 +#: admin.py:347 msgid "Can manage only one OSM export at a time." msgstr "Ne peux gérer qu'un seul export OSM à la fois." -#: admin.py:349 +#: admin.py:352 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:353 +#: admin.py:356 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:360 +#: admin.py:363 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:372 +#: admin.py:375 msgid "Export launched." msgstr "Export lancé." -#: admin.py:376 +#: admin.py:379 #, 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:381 +#: admin.py:384 msgid "Export to osm" msgstr "Exporter vers osm" @@ -141,50 +141,50 @@ 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:77 +#: forms.py:83 msgid "New submission for" msgstr "Nouvelle proposition pour" -#: forms.py:78 +#: forms.py:84 #, 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:80 +#: forms.py:86 msgid "To valid, precise or unvalid this item: " msgstr "Pour valider, préciser ou rejeter cet élément : " -#: forms.py:90 +#: forms.py:96 msgid "Email (optional)" msgstr "Courriel (optionnel) " -#: forms.py:91 +#: forms.py:97 msgid "Object" msgstr "Objet" -#: forms.py:97 +#: forms.py:117 msgid "OSM user" msgstr "Utilisateur OSM" -#: forms.py:98 models.py:1351 +#: forms.py:118 models.py:1500 msgid "Password" msgstr "Mot de passe" -#: forms.py:102 +#: forms.py:122 msgid "API" msgstr "API" -#: forms.py:105 +#: forms.py:125 #, python-format msgid "Test API - %s" msgstr "API de test - %s" -#: forms.py:107 +#: forms.py:127 #, python-format msgid "Main API - %s" msgstr "API principale - %s" -#: forms.py:138 forms.py:142 +#: forms.py:158 forms.py:162 msgid "" "For OSM import you must be provide a filter. Select an area and node/way " "filter." @@ -192,485 +192,530 @@ msgstr "" "Pour les imports OSM vous devez fournir un filtre. Sélectionnez une zone et " "un filtre sur les nœuds/routes." -#: forms.py:146 +#: forms.py:166 msgid "Shapefiles must be provided in a zipped archive." msgstr "" "Les fichiers Shapefiles doivent être fournis regroupés dans une archive zip." -#: forms.py:150 +#: forms.py:170 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:155 +#: forms.py:175 msgid "You have to set \"source\" or \"source file\"." msgstr "Vous devez spécifier le champ « Source » ou « Fichier source »." -#: forms.py:213 +#: forms.py:236 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:217 +#: forms.py:240 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:227 +#: forms.py:250 msgid "This field is mandatory for the selected categories" msgstr "Ce champ est obligatoire pour les catégories sélectionnées" -#: forms.py:462 +#: forms.py:501 msgid "File" msgstr "Fichier" -#: forms.py:468 +#: forms.py:507 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:473 models.py:51 models.py:106 models.py:127 models.py:140 -#: models.py:155 models.py:278 models.py:595 models.py:651 models.py:710 -#: models.py:826 models.py:1155 models.py:1167 models.py:1341 utils.py:482 -#: templates/admin/chimere/managed_modified.html:23 +#: forms.py:512 models.py:53 models.py:101 models.py:163 models.py:184 +#: models.py:197 models.py:212 models.py:375 models.py:720 models.py:776 +#: models.py:835 models.py:953 models.py:1304 models.py:1316 models.py:1490 +#: utils.py:485 templates/admin/chimere/managed_modified.html:23 #: templates/chimere/edit.html:40 templates/chimere/edit_route.html:37 -#: templates/chimere/blocks/alternate_multimedia.html:38 +#: templates/chimere/blocks/alternate_multimedia.html:39 msgid "Name" msgstr "Nom" -#: forms.py:482 models.py:1204 +#: forms.py:521 models.py:1353 msgid "Area" msgstr "Zone" -#: forms.py:522 +#: forms.py:561 msgid "No area selected." msgstr "Pas de zone sélectionnée." -#: forms.py:529 +#: forms.py:568 #, 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." -#: models.py:52 models.py:128 models.py:156 models.py:289 models.py:599 -#: models.py:1173 models.py:1343 +#: forms.py:613 +msgid "Start" +msgstr "Départ" + +#: forms.py:614 +msgid "Finish" +msgstr "Arrivée" + +#: forms.py:615 +msgid "Speed" +msgstr "Vitesse" + +#: models.py:54 +msgid "Mnemonic" +msgstr "Mnémonique" + +#: models.py:56 models.py:102 models.py:185 models.py:213 models.py:368 +#: models.py:724 models.py:1322 models.py:1492 models.py:1533 msgid "Available" msgstr "Disponible" -#: models.py:53 models.py:1352 +#: models.py:57 models.py:173 models.py:186 models.py:230 models.py:778 +#: models.py:850 models.py:1321 models.py:1479 models.py:1491 +msgid "Order" +msgstr "Ordre" + +#: models.py:58 +msgid "Template path" +msgstr "Chemin du patron" + +#: models.py:65 models.py:66 +msgid "Page" +msgstr "Page" + +#: models.py:103 models.py:469 +msgid "Is front page" +msgstr "Est en page principale" + +#: models.py:105 models.py:1501 msgid "Date" msgstr "Date" -#: models.py:55 +#: models.py:107 models.py:777 +msgid "Url" +msgstr "Url" + +#: models.py:108 msgid "Associated areas" msgstr "Zones associées" -#: models.py:61 models.py:62 +#: models.py:114 models.py:115 templates/chimere/blocks/news.html:3 +#: templates/chimere/blocks/news.html:5 msgid "News" msgstr "Nouvelle" -#: models.py:67 +#: models.py:124 msgid "Parameters" msgstr "Paramètres" -#: models.py:71 +#: models.py:128 msgid "TinyUrl" msgstr "Mini-url" -#: models.py:110 models.py:117 models.py:160 +#: models.py:167 models.py:174 models.py:225 msgid "Color theme" msgstr "Thème de couleur" -#: models.py:115 +#: models.py:172 msgid "Code" msgstr "Code" -#: models.py:116 models.py:129 models.py:162 models.py:653 models.py:725 -#: models.py:1172 models.py:1330 models.py:1342 -msgid "Order" -msgstr "Ordre" - -#: models.py:122 +#: models.py:179 msgid "Color" msgstr "Couleur" -#: models.py:135 models.py:153 +#: models.py:192 models.py:210 msgid "Category" msgstr "Catégorie" -#: models.py:141 models.py:591 models.py:711 models.py:892 -#: templates/chimere/blocks/alternate_multimedia.html:42 +#: models.py:198 models.py:716 models.py:836 models.py:1019 +#: templates/chimere/blocks/alternate_multimedia.html:43 msgid "Image" msgstr "Image" -#: models.py:143 models.py:713 models.py:894 +#: models.py:200 models.py:838 models.py:1021 msgid "Height" msgstr "Hauteur" -#: models.py:144 models.py:714 models.py:895 +#: models.py:201 models.py:839 models.py:1022 msgid "Width" msgstr "Largeur" -#: models.py:148 models.py:159 +#: models.py:205 models.py:222 msgid "Icon" msgstr "Icône" -#: models.py:157 +#: models.py:214 msgid "Available for submission" msgstr "Disponible pour soumission" -#: models.py:163 +#: models.py:216 msgid "Marker" msgstr "Point d'intérêt" -#: models.py:164 models.py:888 models.py:905 +#: models.py:217 models.py:1015 models.py:1032 #: templates/chimere/edit_route.html:28 msgid "Route" msgstr "Trajet" -#: models.py:165 +#: models.py:218 msgid "Both" msgstr "Mixte" -#: models.py:166 +#: models.py:219 msgid "Item type" msgstr "Type d'élément" -#: models.py:171 +#: models.py:220 +msgid "Is dated" +msgstr "Est daté" + +#: models.py:223 +msgid "Hover icon" +msgstr "Icône en survol" + +#: models.py:227 +msgid "Displayed in the layer menu" +msgstr "Apparaît dans le menu des couches ?" + +#: models.py:229 +msgid "Routing warn" +msgstr "Avertissement sur les itinéraires" + +#: models.py:235 msgid "Sub-category" msgstr "Sous-catégorie" -#: models.py:172 +#: models.py:236 msgid "Sub-categories" msgstr "Sous-catégories" -#: models.py:230 +#: models.py:320 msgid "Importer type" msgstr "Type d'import" -#: models.py:232 +#: models.py:322 msgid "Filter" msgstr "Filtre" -#: models.py:234 templates/chimere/blocks/alternate_multimedia.html:48 +#: models.py:324 templates/chimere/blocks/alternate_multimedia.html:49 msgid "Web address" msgstr "Adresse web" -#: models.py:236 +#: models.py:326 msgid "Source file" msgstr "Fichier source" -#: models.py:238 +#: models.py:328 msgid "Name by default" msgstr "Nom par défaut" -#: models.py:240 +#: models.py:330 msgid "SRID" msgstr "SRID" -#: models.py:241 +#: models.py:331 msgid "Zipped file" msgstr "Fichier zippé" -#: models.py:242 +#: models.py:332 msgid "Overwrite existing data" msgstr "Écraser les données existantes" -#: models.py:244 +#: models.py:334 msgid "Get description from source" -msgstr "Obtenir une description depuis la source de données" +msgstr "Obtenir une description depuis la source" -#: models.py:246 +#: models.py:336 msgid "Default description" msgstr "Description par défaut" -#: models.py:248 models.py:305 +#: models.py:338 models.py:396 msgid "Origin" msgstr "Origine" -#: models.py:250 models.py:307 +#: models.py:340 models.py:398 msgid "License" msgstr "Licence" -#: models.py:253 +#: models.py:343 msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:254 utils.py:486 +#: models.py:344 utils.py:489 msgid "State" msgstr "État" -#: models.py:256 +#: models.py:346 msgid "Automatically associate a marker to a way" msgstr "Associer automatiquement un marqueur à une route" -#: models.py:260 +#: models.py:350 msgid "Importer" msgstr "Import" -#: models.py:280 -msgid "Submitter session key" -msgstr "Clé de session du demandeur" - -#: models.py:282 -msgid "Submitter name or nickname" -msgstr "Nom ou pseudo du demandeur" - -#: models.py:284 -msgid "Submitter email" -msgstr "Courriel du demandeur" - -#: models.py:286 -msgid "Submitter comment" -msgstr "Commentaire du demandeur" - -#: models.py:288 +#: models.py:367 msgid "Submited" msgstr "Soumis" -#: models.py:290 +#: models.py:369 msgid "Modified" msgstr "Modifié" -#: models.py:291 +#: models.py:370 msgid "Disabled" msgstr "Désactivé" -#: models.py:292 +#: models.py:371 msgid "Imported" msgstr "Importé" -#: models.py:294 +#: models.py:377 +msgid "Submitter session key" +msgstr "Clé de session du demandeur" + +#: models.py:379 +msgid "Submitter name or nickname" +msgstr "Nom ou pseudo du demandeur" + +#: models.py:381 +msgid "Submitter email" +msgstr "Courriel du demandeur" + +#: models.py:383 +msgid "Submitter comment" +msgstr "Commentaire du demandeur" + +#: models.py:385 models.py:1195 msgid "Status" msgstr "État" -#: models.py:295 +#: models.py:386 msgid "Import key" msgstr "Clé d'import" -#: models.py:297 +#: models.py:388 msgid "Import version" msgstr "Version de l'import" -#: models.py:299 +#: models.py:390 msgid "Source" msgstr "Source" -#: models.py:301 +#: models.py:392 msgid "Modified since last import" msgstr "Modifié depuis le dernier import" -#: models.py:303 +#: models.py:394 msgid "Not to be exported to OSM" msgstr "À ne pas exporter vers OSM" -#: models.py:309 templates/chimere/edit.html:57 +#: models.py:400 templates/chimere/edit.html:57 #: templates/chimere/edit_route.html:53 msgid "Start date" msgstr "Date de début" -#: models.py:310 +#: models.py:401 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:312 templates/chimere/edit.html:63 +#: models.py:403 templates/chimere/edit.html:63 #: templates/chimere/edit_route.html:59 msgid "End date" msgstr "Date de fin" -#: models.py:313 +#: models.py:404 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:366 +#: models.py:461 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:367 utils.py:488 +#: models.py:462 utils.py:491 msgid "Localisation" msgstr "Localisation" -#: models.py:369 +#: models.py:464 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:373 utils.py:487 templates/admin/chimere/managed_modified.html:31 +#: models.py:468 utils.py:490 templates/admin/chimere/managed_modified.html:31 #: templates/chimere/edit.html:50 templates/chimere/edit_route.html:47 msgid "Description" msgstr "Description" -#: models.py:435 models.py:1377 +#: models.py:539 models.py:1543 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:589 +#: models.py:714 msgid "Audio" msgstr "Audio" -#: models.py:590 +#: models.py:715 msgid "Video" msgstr "Vidéo" -#: models.py:592 +#: models.py:717 msgid "Other" msgstr "Autre" -#: models.py:593 +#: models.py:718 msgid "Media type" msgstr "Type de media" -#: models.py:596 +#: models.py:721 msgid "Mime type" msgstr "Type mime" -#: models.py:598 +#: models.py:723 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:602 +#: models.py:727 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:603 +#: models.py:728 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:612 +#: models.py:737 msgid "Automatic recognition" msgstr "Reconnaissance automatique" -#: models.py:638 +#: models.py:763 msgid "Extension name" msgstr "Nom de l'extension" -#: models.py:640 +#: models.py:765 msgid "Associated multimedia type" msgstr "Type de multimedia associé" -#: models.py:644 +#: models.py:769 msgid "Multimedia extension" msgstr "Extension multimedia" -#: models.py:645 +#: models.py:770 msgid "Multimedia extensions" msgstr "Extensions multimedia" -#: models.py:652 -msgid "Url" -msgstr "Url" - -#: models.py:655 models.py:715 +#: models.py:780 models.py:840 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:660 +#: models.py:785 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:661 +#: models.py:786 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: models.py:717 +#: models.py:842 msgid "Thumbnail" msgstr "Miniature" -#: models.py:721 +#: models.py:846 msgid "Thumbnail height" msgstr "Hauteur de la miniature" -#: models.py:723 +#: models.py:848 msgid "Thumbnail width" msgstr "Largeur de la miniature" -#: models.py:732 +#: models.py:857 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:733 +#: models.py:858 msgid "Picture files" msgstr "Fichiers d'image" -#: models.py:827 +#: models.py:954 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:829 +#: models.py:956 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:831 +#: models.py:958 msgid "KML" msgstr "KML" -#: models.py:831 +#: models.py:958 msgid "GPX" msgstr "GPX" -#: models.py:836 +#: models.py:963 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:837 +#: models.py:964 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:887 +#: models.py:1014 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:891 +#: models.py:1018 msgid "Associated file" msgstr "Fichier associé" -#: models.py:896 +#: models.py:1023 msgid "Has an associated marker" msgstr "Dispose d'un marqueur associé" -#: models.py:1156 +#: models.py:1305 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:1162 +#: models.py:1311 msgid "Layer" msgstr "Couche" -#: models.py:1168 +#: models.py:1317 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:1170 templates/chimere/blocks/welcome.html:3 +#: models.py:1319 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:1174 +#: models.py:1323 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:1176 +#: models.py:1325 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:1178 +#: models.py:1327 msgid "Default area" msgstr "Zone par défaut" -#: models.py:1179 +#: models.py:1328 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:1183 +#: models.py:1332 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:1185 +#: models.py:1334 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:1186 +#: models.py:1335 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -678,64 +723,72 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:1190 models.py:1346 +#: models.py:1339 models.py:1495 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:1191 +#: models.py:1340 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:1193 +#: models.py:1342 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:1195 +#: models.py:1344 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:1331 +#: models.py:1480 widgets.py:88 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:1335 models.py:1336 +#: models.py:1484 models.py:1485 msgid "Layers" msgstr "Couches" -#: models.py:1344 +#: models.py:1493 msgid "Mandatory" msgstr "Obligatoire" -#: models.py:1347 +#: models.py:1496 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:1349 +#: models.py:1498 msgid "Text" msgstr "Texte" -#: models.py:1350 +#: models.py:1499 msgid "Long text" msgstr "Texte long" -#: models.py:1357 +#: models.py:1502 +msgid "Choices" +msgstr "Choix" + +#: models.py:1510 msgid "Type" msgstr "Type" -#: models.py:1362 models.py:1379 +#: models.py:1515 models.py:1531 models.py:1545 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:1380 +#: models.py:1532 models.py:1546 msgid "Value" msgstr "Valeur" -#: models.py:1384 +#: models.py:1538 +msgid "Model property choice" +msgstr "Choix pour les modèles de propriété" + +#: models.py:1557 msgid "Property" msgstr "Propriété" @@ -789,69 +842,70 @@ msgstr "Export échoué" msgid "Export canceled" msgstr "Export annulé" -#: utils.py:145 utils.py:194 +#: utils.py:148 utils.py:197 msgid "Bad zip file" msgstr "Mauvais fichier zip" -#: utils.py:197 +#: utils.py:200 msgid "Missing file(s) inside the zip file" msgstr "Fichier(s) manquant(s) dans l'archive zip" -#: utils.py:238 +#: utils.py:241 msgid "Bad XML file" msgstr "Mauvais fichier XML" -#: utils.py:325 +#: utils.py:328 msgid "Error while reading the data source." msgstr "Erreur lors de la lecture de la source." -#: utils.py:343 +#: utils.py:346 #, 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:364 +#: utils.py:367 +#, python-format msgid "Type of geographic item (%s) of this shapefile is not managed by Chimère." msgstr "" "Les types des éléments géographiques (%s) de ce fichier Shapefile ne sont pas " -"gérés par Chimère." + "gérés par Chimère." -#: utils.py:384 +#: utils.py:387 msgid "Bad Shapefile" msgstr "Mauvais fichier Shapefile" -#: utils.py:426 +#: utils.py:429 msgid "Could not create file!" msgstr "Ne peut pas créer le fichier !" -#: utils.py:437 +#: utils.py:440 msgid "Failed to create field" msgstr "Ne peut pas créer un champ" -#: utils.py:483 templates/admin/chimere/managed_modified.html:25 +#: utils.py:486 templates/admin/chimere/managed_modified.html:25 #: templates/chimere/edit.html:45 templates/chimere/edit_route.html:42 #: templates/chimere/main_map.html:13 #: templates/chimere/main_map_simple.html:10 msgid "Categories" msgstr "Catégories" -#: utils.py:516 +#: utils.py:519 msgid "Invalid CSV format" msgstr "Fichier CSV non valide" -#: utils.py:594 +#: utils.py:597 msgid "RSS feed is not well formed" msgstr "Flux RSS non valide" -#: utils.py:670 +#: utils.py:673 msgid "Nothing to import" msgstr "Rien à importer" -#: utils.py:754 +#: utils.py:757 msgid "New items imported - validate them before exporting" msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter" -#: utils.py:756 +#: utils.py:759 msgid "" "There are items from a former import not yet validated - validate them " "before exporting" @@ -859,19 +913,19 @@ msgstr "" "Il y a des éléments d'un import précédent pas encore validé - Validez les " "avant d'exporter" -#: utils.py:768 +#: utils.py:771 msgid "Bad params - programming error" msgstr "Mauvais paramètres - erreur de programmation" -#: utils.py:778 +#: utils.py:781 msgid "Bad param" msgstr "Mauvais paramètre" -#: utils.py:793 +#: utils.py:796 msgid "No non ambigious tag is defined in the XAPI request" msgstr "Pas de tag non ambigü définis dans la requête XAPI" -#: utils.py:795 +#: utils.py:798 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" @@ -880,19 +934,19 @@ msgstr "" "vouloir lancer la requête sur la planète entière fixez la « bounding box » " "à -180,-90,180,90" -#: views.py:240 +#: views.py:290 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:325 +#: views.py:375 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:435 +#: views.py:487 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:438 +#: views.py:490 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." @@ -901,48 +955,56 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:442 +#: views.py:494 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:578 +#: views.py:663 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:686 +#: views.py:763 +msgid "Bad geometry" +msgstr "Géométrie incorrecte" + +#: views.py:848 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:216 +#: widgets.py:242 +msgid "Street, City, Country" +msgstr "Rue, Commune, Pays" + +#: widgets.py:311 msgid "Latitude" msgstr "Latitude" -#: widgets.py:216 +#: widgets.py:311 msgid "Longitude" msgstr "Longitude" -#: widgets.py:240 +#: widgets.py:335 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:292 +#: widgets.py:391 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:293 +#: widgets.py:392 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:295 +#: 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:296 +#: widgets.py:395 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:297 +#: widgets.py:396 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -950,7 +1012,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:299 +#: widgets.py:398 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -958,17 +1020,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:304 +#: widgets.py:403 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:305 +#: 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:306 +#: widgets.py:405 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -976,7 +1038,7 @@ msgstr "" "Pour supprimer un point, mettez le curseur de la souris sur celui-ci et " "appuyez sur le touche « d » ou « Suppr »." -#: widgets.py:308 +#: widgets.py:407 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -985,51 +1047,51 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:315 +#: 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:318 +#: widgets.py:417 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:319 +#: widgets.py:418 msgid "or" msgstr "ou" -#: widgets.py:324 +#: widgets.py:423 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:347 +#: widgets.py:446 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:347 +#: widgets.py:446 msgid "Draw" msgstr "Tracer" -#: widgets.py:437 +#: 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:494 +#: widgets.py:593 msgid "Type:" msgstr "Type :" -#: widgets.py:494 +#: widgets.py:593 msgid "Node" msgstr "Nœud" -#: widgets.py:495 +#: widgets.py:594 msgid "Way" msgstr "Route" -#: widgets.py:506 +#: 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' " @@ -1039,39 +1101,39 @@ msgstr "" "liste des clés est disponible <a href='https://wiki.openstreetmap.org/wiki/" "FR:Map_Features' target='_blank'>ici</a>." -#: widgets.py:513 +#: widgets.py:612 msgid "Tag:" msgstr "Clé/valeur :" -#: widgets.py:517 +#: widgets.py:616 msgid "You have to select an area." msgstr "Vous devez sélectionner une zone." -#: widgets.py:519 +#: widgets.py:618 msgid "You have to select a type." msgstr "Vous devez sélectionner un type." -#: widgets.py:521 +#: widgets.py:620 msgid "You have to insert a filter tag." msgstr "Vous devez saisir une clé=valeur." -#: widgets.py:523 +#: 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:526 +#: 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:534 +#: widgets.py:633 msgid "Refresh" msgstr "Rafraîchir" -#: widgets.py:600 +#: widgets.py:699 msgid "Select..." msgstr "Sélectionner..." @@ -1166,7 +1228,7 @@ msgstr "" "Après ajout/modification de modèle de propriété vous aurez à recharger le " "serveur web." -#: templates/chimere/base.html:11 +#: templates/chimere/base.html:12 msgid "You must enable JavaScript in your browser to display Chimère." msgstr "" "Vous devez activer le JavaScript dans votre navigateur pour afficher Chimère." @@ -1210,14 +1272,6 @@ msgstr "Proposer une modification" msgid "I would like to propose an amendment for this item:" msgstr "Je souhaiterais proposer une modification pour cet élément :" -#: templates/chimere/detail.html:40 -msgid "Share on" -msgstr "Partager sur" - -#: templates/chimere/detail.html:44 -msgid "Share" -msgstr "Partager" - #: templates/chimere/edit.html:20 msgid "Error" msgstr "Erreur" @@ -1279,7 +1333,7 @@ msgstr "Commentaires au sujet de votre proposition" msgid "Upload in progress. Please wait..." msgstr "Dépôt en cours. Veuillez patienter..." -#: templates/chimere/edit.html:152 templates/chimere/edit_route.html:78 +#: templates/chimere/edit.html:153 templates/chimere/edit_route.html:78 msgid "Propose" msgstr "Proposez" @@ -1291,7 +1345,7 @@ msgstr "Modifier un trajet" msgid "Add a route" msgstr "Ajout d'un nouveau trajet" -#: templates/chimere/main_map.html:27 +#: templates/chimere/main_map.html:35 msgid "Simple map" msgstr "Carte simple" @@ -1307,17 +1361,17 @@ msgstr "Déposer un fichier" msgid "Upload" msgstr "Déposer" -#: templates/chimere/blocks/alternate_multimedia.html:32 -#: templates/chimere/blocks/alternate_multimedia.html:50 +#: 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" -#: templates/chimere/blocks/alternate_multimedia.html:34 -msgid "Add multimedia from your computer or a site" +#: templates/chimere/blocks/alternate_multimedia.html:35 +msgid "Add multimedia from your computer or a website" msgstr "Ajoutez du multimedia depuis votre ordinateur ou un site web" -#: templates/chimere/blocks/alternate_multimedia.html:35 +#: templates/chimere/blocks/alternate_multimedia.html:36 msgid "" "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu luctus " "ipsum. Donec vel urna a turpis consectetur consectetur. Vestibulum ut enim " @@ -1327,31 +1381,31 @@ msgstr "" "ipsum. Donec vel urna a turpis consectetur consectetur. Vestibulum ut enim " "vel odio porta vulputate." -#: templates/chimere/blocks/alternate_multimedia.html:43 +#: templates/chimere/blocks/alternate_multimedia.html:44 msgid "Audio, video, other..." msgstr "Audio, vidéo, autre..." -#: templates/chimere/blocks/alternate_multimedia.html:46 +#: templates/chimere/blocks/alternate_multimedia.html:47 msgid "Download" msgstr "Télécharger" -#: templates/chimere/blocks/alternate_multimedia.html:47 +#: templates/chimere/blocks/alternate_multimedia.html:48 msgid "Or" msgstr "Ou" -#: templates/chimere/blocks/alternate_multimedia.html:76 +#: templates/chimere/blocks/alternate_multimedia.html:80 msgid "You must provide a name." msgstr "Vous devez renseigner le nom." -#: templates/chimere/blocks/alternate_multimedia.html:81 +#: templates/chimere/blocks/alternate_multimedia.html:85 msgid "You must choose a media type." msgstr "Vous devez renseigner un type de fichier média." -#: templates/chimere/blocks/alternate_multimedia.html:87 +#: templates/chimere/blocks/alternate_multimedia.html:91 msgid "You must provide a file or a web address." msgstr "Vous devez renseigner un fichier ou une adresse web." -#: templates/chimere/blocks/alternate_multimedia.html:92 +#: templates/chimere/blocks/alternate_multimedia.html:96 msgid "You must provide a web address." msgstr "Vous devez fournir une adresse web." @@ -1390,16 +1444,101 @@ msgstr "Carte" msgid "Loading of the map in progress" msgstr "Chargement de la carte en cours" -#: templates/chimere/blocks/map.html:18 +#: templates/chimere/blocks/map.html:13 +msgid "Display options" +msgstr "Options d'affichage" + +#: templates/chimere/blocks/map.html:15 +msgid "Map type" +msgstr "Type de carte" + +#: templates/chimere/blocks/map.html:24 msgid "Permalink" msgstr "Lien permanent" +#: templates/chimere/blocks/map_menu.html:5 +msgctxt "routing" +msgid "From" +msgstr "En partir" + +#: templates/chimere/blocks/map_menu.html:6 +msgctxt "routing" +msgid "Add a step" +msgstr "Ajout d'une étape" + +#: templates/chimere/blocks/map_menu.html:7 +msgctxt "routing" +msgid "To" +msgstr "Y aller" + +#: templates/chimere/blocks/map_menu.html:8 +msgctxt "routing" +msgid "Clear the itinerary" +msgstr "Effacer l'itinéraire" + +#: templates/chimere/blocks/map_menu.html:10 +msgid "Zoom in" +msgstr "Zoomer en avant" + +#: templates/chimere/blocks/map_menu.html:11 +msgid "Zoom out" +msgstr "Zoomer en arrière" + +#: templates/chimere/blocks/map_menu.html:12 +msgid "Center the map here" +msgstr "Centrer la carte ici" + #: templates/chimere/blocks/multimedia_file.html:19 msgid "Please use a modern browser or install the non free Flash-Plugin." msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." +#: templates/chimere/blocks/news.html:42 +#: templates/chimere/blocks/welcome.html:52 +msgid "See it on the map" +msgstr "Voir sur la carte" + +#: templates/chimere/blocks/routing.html:5 +msgid "Itinerary" +msgstr "Itinéraire" + +#: templates/chimere/blocks/routing.html:16 +msgid "Add a step" +msgstr "Ajouter une étape" + +#: templates/chimere/blocks/routing.html:17 +msgid "Search" +msgstr "Rechercher" + +#: templates/chimere/blocks/routing.html:23 +msgid "Modify" +msgstr "Modifier" + +#: templates/chimere/blocks/routing.html:26 +msgid "New search" +msgstr "Nouvelle recherche" + +#: templates/chimere/blocks/routing.html:34 +msgid "Start:" +msgstr "Départ :" + +#: templates/chimere/blocks/routing.html:38 +msgid "Finish:" +msgstr "Arrivée :" + +#: templates/chimere/blocks/routing.html:44 +msgid "Step" +msgstr "Étape" + +#: templates/chimere/blocks/share_bar.html:3 +msgid "Share on" +msgstr "Partager sur" + +#: templates/chimere/blocks/share_bar.html:7 +msgid "Share" +msgstr "Partager" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -1428,10 +1567,6 @@ msgstr "Retourner à la carte" msgid "Welcome" msgstr "Accueil" -#: templates/chimere/blocks/welcome.html:52 -msgid "See it on the map" -msgstr "Voir sur la carte" - #: templates/chimere/feeds/rss.html:13 msgid "Subscribe to RSS feed" msgstr "Souscrire à un flux RSS" @@ -1472,6 +1607,11 @@ msgstr "Description :" msgid ":" msgstr " :" +#: templatetags/chimere_tags.py:80 +#, python-format +msgid "Welcome to the %s" +msgstr "Bienvenue sur %s" + #~ msgid "Advanced options" #~ msgstr "Options avancées" diff --git a/chimere/migrations/0001_initial.py b/chimere/migrations/0001_initial.py index 74f67a6..c98ec01 100644 --- a/chimere/migrations/0001_initial.py +++ b/chimere/migrations/0001_initial.py @@ -1,319 +1,605 @@ -# encoding: utf-8 +# -*- 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 'News' - db.create_table('main_news', ( - ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), - ('date', self.gf('django.db.models.fields.DateField')(auto_now_add=True, blank=True)), - ('content', self.gf('django.db.models.fields.TextField')()), + db.create_table('chimere_news', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('date', self.gf('django.db.models.fields.DateField')(auto_now_add=True, blank=True)), + ('content', self.gf('django.db.models.fields.TextField')()), )) db.send_create_signal('chimere', ['News']) + # Adding M2M table for field areas on 'News' + db.create_table('chimere_news_areas', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('news', models.ForeignKey(orm['chimere.news'], null=False)), + ('area', models.ForeignKey(orm['chimere.area'], null=False)) + )) + db.create_unique('chimere_news_areas', ['news_id', 'area_id']) + # Adding model 'TinyUrl' - db.create_table('main_tinyurl', ( + db.create_table('chimere_tinyurl', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('parameters', self.gf('django.db.models.fields.CharField')(max_length=500)), )) db.send_create_signal('chimere', ['TinyUrl']) # Adding model 'ColorTheme' - db.create_table('main_colortheme', ( + db.create_table('chimere_colortheme', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), )) db.send_create_signal('chimere', ['ColorTheme']) # Adding model 'Color' - db.create_table('main_color', ( - ('code', self.gf('django.db.models.fields.CharField')(max_length=6)), - ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'])), + db.create_table('chimere_color', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('code', self.gf('django.db.models.fields.CharField')(max_length=6)), ('order', self.gf('django.db.models.fields.IntegerField')()), + ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'])), )) db.send_create_signal('chimere', ['Color']) # Adding model 'Category' - db.create_table('main_category', ( - ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), - ('order', self.gf('django.db.models.fields.IntegerField')()), + db.create_table('chimere_category', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), )) db.send_create_signal('chimere', ['Category']) # Adding model 'Icon' - db.create_table('main_icon', ( - ('width', self.gf('django.db.models.fields.IntegerField')()), - ('image', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), - ('height', self.gf('django.db.models.fields.IntegerField')()), + db.create_table('chimere_icon', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('image', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), + ('height', self.gf('django.db.models.fields.IntegerField')()), + ('width', self.gf('django.db.models.fields.IntegerField')()), )) db.send_create_signal('chimere', ['Icon']) # Adding model 'SubCategory' - db.create_table('main_subcategory', ( - ('category', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Category'])), - ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), - ('order', self.gf('django.db.models.fields.IntegerField')()), - ('item_type', self.gf('django.db.models.fields.CharField')(max_length=1)), - ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'], null=True, blank=True)), + db.create_table('chimere_subcategory', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('category', self.gf('django.db.models.fields.related.ForeignKey')(related_name='subcategories', to=orm['chimere.Category'])), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('submission', self.gf('django.db.models.fields.BooleanField')(default=True)), ('icon', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Icon'])), + ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'], null=True, blank=True)), + ('order', self.gf('django.db.models.fields.IntegerField')(default=1000)), + ('item_type', self.gf('django.db.models.fields.CharField')(max_length=1)), )) db.send_create_signal('chimere', ['SubCategory']) - # Adding M2M table for field areas on 'SubCategory' - db.create_table('main_subcategory_areas', ( + # Adding model 'Importer' + db.create_table('chimere_importer', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('importer_type', self.gf('django.db.models.fields.CharField')(max_length=4)), + ('filtr', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('source', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('source_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True)), + ('default_name', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('srid', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('zipped', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('get_description', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('default_description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + ('origin', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('license', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('state', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('associate_marker_to_way', self.gf('django.db.models.fields.BooleanField')(default=False)), + )) + db.send_create_signal('chimere', ['Importer']) + + # Adding M2M table for field categories on 'Importer' + db.create_table('chimere_importer_categories', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)), - ('area', models.ForeignKey(orm['chimere.area'], null=False)) + ('importer', models.ForeignKey(orm['chimere.importer'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) )) - db.create_unique('main_subcategory_areas', ['subcategory_id', 'area_id']) + db.create_unique('chimere_importer_categories', ['importer_id', 'subcategory_id']) # Adding model 'Marker' - db.create_table('main_marker', ( - ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), - ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), + db.create_table('chimere_marker', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('submiter_session_key', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('submiter_name', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('submiter_email', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True)), + ('submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True, blank=True)), + ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('import_key', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('import_version', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('import_source', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('modified_since_import', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('not_for_osm', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('origin', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('license', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), ('end_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('ref_item', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='submited_marker', null=True, to=orm['chimere.Marker'])), ('point', self.gf('chimere.widgets.PointField')()), - ('route', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Route'], null=True, blank=True)), - ('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), - ('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), - ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), ('available_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('route', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='associated_marker', null=True, to=orm['chimere.Route'])), + ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), )) db.send_create_signal('chimere', ['Marker']) # Adding M2M table for field categories on 'Marker' - db.create_table('main_marker_categories', ( + db.create_table('chimere_marker_categories', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ('marker', models.ForeignKey(orm['chimere.marker'], null=False)), ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) )) - db.create_unique('main_marker_categories', ['marker_id', 'subcategory_id']) + db.create_unique('chimere_marker_categories', ['marker_id', 'subcategory_id']) + + # Adding model 'MultimediaType' + db.create_table('chimere_multimediatype', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('media_type', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('mime_type', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)), + ('iframe', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=True)), + )) + db.send_create_signal('chimere', ['MultimediaType']) + + # 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']) + + # Adding model 'MultimediaFile' + db.create_table('chimere_multimediafile', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('url', self.gf('django.db.models.fields.URLField')(max_length=200)), + ('order', self.gf('django.db.models.fields.IntegerField')(default=1)), + ('multimedia_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.MultimediaType'], null=True, blank=True)), + ('miniature', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('marker', self.gf('django.db.models.fields.related.ForeignKey')(related_name='multimedia_files', to=orm['chimere.Marker'])), + )) + db.send_create_signal('chimere', ['MultimediaFile']) + + # Adding model 'PictureFile' + db.create_table('chimere_picturefile', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), + ('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('miniature', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('thumbnailfile', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), + ('thumbnailfile_height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('thumbnailfile_width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('order', self.gf('django.db.models.fields.IntegerField')(default=1)), + ('marker', self.gf('django.db.models.fields.related.ForeignKey')(related_name='pictures', to=orm['chimere.Marker'])), + )) + db.send_create_signal('chimere', ['PictureFile']) # Adding model 'RouteFile' - db.create_table('main_routefile', ( - ('file_type', self.gf('django.db.models.fields.CharField')(max_length=1)), - ('raw_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)), - ('simplified_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True)), + db.create_table('chimere_routefile', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('raw_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)), + ('simplified_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True)), + ('file_type', self.gf('django.db.models.fields.CharField')(max_length=1)), )) db.send_create_signal('chimere', ['RouteFile']) # Adding model 'Route' - db.create_table('main_route', ( - ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), - ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), + db.create_table('chimere_route', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('submiter_session_key', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('submiter_name', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('submiter_email', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True)), + ('submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True, blank=True)), + ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('import_key', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('import_version', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('import_source', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)), + ('modified_since_import', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('not_for_osm', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('origin', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('license', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), ('end_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('ref_item', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='submited_route', null=True, to=orm['chimere.Route'])), ('route', self.gf('chimere.widgets.RouteField')()), + ('associated_file', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.RouteFile'], null=True, blank=True)), + ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), ('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), ('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), - ('associated_file', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.RouteFile'], null=True, blank=True)), - ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('has_associated_marker', self.gf('django.db.models.fields.BooleanField')(default=True)), )) db.send_create_signal('chimere', ['Route']) # Adding M2M table for field categories on 'Route' - db.create_table('main_route_categories', ( + db.create_table('chimere_route_categories', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ('route', models.ForeignKey(orm['chimere.route'], null=False)), ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) )) - db.create_unique('main_route_categories', ['route_id', 'subcategory_id']) + db.create_unique('chimere_route_categories', ['route_id', 'subcategory_id']) - # Adding model 'Area' - db.create_table('main_area', ( - ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + # Adding model 'Layer' + db.create_table('chimere_layer', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), - ('urn', self.gf('django.db.models.fields.SlugField')(db_index=True, unique=True, max_length=50, blank=True)), + ('layer_code', self.gf('django.db.models.fields.TextField')(max_length=300)), + )) + db.send_create_signal('chimere', ['Layer']) + + # Adding model 'Area' + db.create_table('chimere_area', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('urn', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50, blank=True)), + ('welcome_message', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + ('order', self.gf('django.db.models.fields.IntegerField')(unique=True)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=False)), ('upper_left_corner', self.gf('django.contrib.gis.db.models.fields.PointField')(default='POINT(0 0)')), - ('order', self.gf('django.db.models.fields.IntegerField')()), ('lower_right_corner', self.gf('django.contrib.gis.db.models.fields.PointField')(default='POINT(0 0)')), + ('default', self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True)), + ('dynamic_categories', self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True)), + ('external_css', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True)), + ('restrict_to_extent', self.gf('django.db.models.fields.BooleanField')(default=False)), )) db.send_create_signal('chimere', ['Area']) - # Adding model 'PropertyModel' - db.create_table('main_propertymodel', ( - ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + # Adding M2M table for field default_subcategories on 'Area' + db.create_table('chimere_area_default_subcategories', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('area', models.ForeignKey(orm['chimere.area'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) + )) + db.create_unique('chimere_area_default_subcategories', ['area_id', 'subcategory_id']) + + # Adding M2M table for field subcategories on 'Area' + db.create_table('chimere_subcategory_areas', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('area', models.ForeignKey(orm['chimere.area'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) + )) + db.create_unique('chimere_subcategory_areas', ['area_id', 'subcategory_id']) + + # Adding model 'AreaLayers' + db.create_table('chimere_arealayers', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('area', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Area'])), + ('layer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Layer'])), ('order', self.gf('django.db.models.fields.IntegerField')()), - ('type', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('default', self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True)), + )) + db.send_create_signal('chimere', ['AreaLayers']) + + # Adding model 'PropertyModel' + db.create_table('chimere_propertymodel', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('available', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('mandatory', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('type', self.gf('django.db.models.fields.CharField')(max_length=1)), )) db.send_create_signal('chimere', ['PropertyModel']) + # 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']) + # Adding model 'Property' - db.create_table('main_property', ( - ('marker', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Marker'])), + db.create_table('chimere_property', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('value', self.gf('django.db.models.fields.TextField')()), + ('marker', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Marker'])), ('propertymodel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.PropertyModel'])), + ('value', self.gf('django.db.models.fields.TextField')()), )) db.send_create_signal('chimere', ['Property']) - - + + def backwards(self, orm): - # Deleting model 'News' - db.delete_table('main_news') + db.delete_table('chimere_news') + + # Removing M2M table for field areas on 'News' + db.delete_table('chimere_news_areas') # Deleting model 'TinyUrl' - db.delete_table('main_tinyurl') + db.delete_table('chimere_tinyurl') # Deleting model 'ColorTheme' - db.delete_table('main_colortheme') + db.delete_table('chimere_colortheme') # Deleting model 'Color' - db.delete_table('main_color') + db.delete_table('chimere_color') # Deleting model 'Category' - db.delete_table('main_category') + db.delete_table('chimere_category') # Deleting model 'Icon' - db.delete_table('main_icon') + db.delete_table('chimere_icon') # Deleting model 'SubCategory' - db.delete_table('main_subcategory') + db.delete_table('chimere_subcategory') + + # Deleting model 'Importer' + db.delete_table('chimere_importer') - # Removing M2M table for field areas on 'SubCategory' - db.delete_table('main_subcategory_areas') + # Removing M2M table for field categories on 'Importer' + db.delete_table('chimere_importer_categories') # Deleting model 'Marker' - db.delete_table('main_marker') + db.delete_table('chimere_marker') # Removing M2M table for field categories on 'Marker' - db.delete_table('main_marker_categories') + db.delete_table('chimere_marker_categories') + + # Deleting model 'MultimediaType' + db.delete_table('chimere_multimediatype') + + # Deleting model 'MultimediaExtension' + db.delete_table('chimere_multimediaextension') + + # Deleting model 'MultimediaFile' + db.delete_table('chimere_multimediafile') + + # Deleting model 'PictureFile' + db.delete_table('chimere_picturefile') # Deleting model 'RouteFile' - db.delete_table('main_routefile') + db.delete_table('chimere_routefile') # Deleting model 'Route' - db.delete_table('main_route') + db.delete_table('chimere_route') # Removing M2M table for field categories on 'Route' - db.delete_table('main_route_categories') + db.delete_table('chimere_route_categories') + + # Deleting model 'Layer' + db.delete_table('chimere_layer') # Deleting model 'Area' - db.delete_table('main_area') + db.delete_table('chimere_area') + + # Removing M2M table for field default_subcategories on 'Area' + db.delete_table('chimere_area_default_subcategories') + + # Removing M2M table for field subcategories on 'Area' + db.delete_table('chimere_subcategory_areas') + + # Deleting model 'AreaLayers' + db.delete_table('chimere_arealayers') # Deleting model 'PropertyModel' - db.delete_table('main_propertymodel') + db.delete_table('chimere_propertymodel') + + # Removing M2M table for field subcategories on 'PropertyModel' + db.delete_table('chimere_propertymodel_subcategories') # Deleting model 'Property' - db.delete_table('main_property') - - + db.delete_table('chimere_property') + + models = { 'chimere.area': { - 'Meta': {'object_name': 'Area', 'db_table': "'main_area'"}, - 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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', [], {}), + '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', [], {'db_index': 'True', 'unique': 'True', 'max_length': '50', 'blank': 'True'}) + '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': {'object_name': 'Category', 'db_table': "'main_category'"}, - 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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': {'object_name': 'Color', 'db_table': "'main_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', 'db_table': "'main_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', 'db_table': "'main_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_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + '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'}), + 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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': {'object_name': 'Marker', 'db_table': "'main_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'}), - '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'}), - 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + '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', [], {}), - 'route': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Route']", 'null': 'True', 'blank': 'True'}), + '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'}), - 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + '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', 'db_table': "'main_news'"}, - 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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', 'db_table': "'main_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': {'object_name': 'PropertyModel', 'db_table': "'main_propertymodel'"}, - 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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': {'object_name': 'Route', 'db_table': "'main_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': {'object_name': 'RouteFile', 'db_table': "'main_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'}), @@ -321,22 +607,22 @@ class Migration(SchemaMigration): 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) }, 'chimere.subcategory': { - 'Meta': {'object_name': 'SubCategory', 'db_table': "'main_subcategory'"}, - 'areas': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'to': "orm['chimere.Area']"}), - 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + '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', [], {}) + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}), + 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) }, 'chimere.tinyurl': { - 'Meta': {'object_name': 'TinyUrl', 'db_table': "'main_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'] + + complete_apps = ['chimere']
\ No newline at end of file diff --git a/chimere/migrations/0002_auto__add_propertymodelchoice__add_page__add_field_subcategory_dated__.py b/chimere/migrations/0002_auto__add_propertymodelchoice__add_page__add_field_subcategory_dated__.py new file mode 100644 index 0000000..e9dd34c --- /dev/null +++ b/chimere/migrations/0002_auto__add_propertymodelchoice__add_page__add_field_subcategory_dated__.py @@ -0,0 +1,361 @@ +# -*- 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 'PropertyModelChoice' + db.create_table('chimere_propertymodelchoice', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('propertymodel', self.gf('django.db.models.fields.related.ForeignKey')(related_name='choices', to=orm['chimere.PropertyModel'])), + ('value', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=True)), + )) + db.send_create_signal('chimere', ['PropertyModelChoice']) + + # Adding model 'Page' + db.create_table('chimere_page', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('mnemonic', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), + ('available', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('order', self.gf('django.db.models.fields.IntegerField')(default=10, null=True, blank=True)), + ('template_path', self.gf('django.db.models.fields.CharField')(max_length=150, null=True, blank=True)), + ('content', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + )) + db.send_create_signal('chimere', ['Page']) + + # Adding field 'SubCategory.dated' + db.add_column('chimere_subcategory', 'dated', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'SubCategory.description' + db.add_column('chimere_subcategory', 'description', + self.gf('django.db.models.fields.TextField')(null=True, blank=True), + keep_default=False) + + # Adding field 'SubCategory.hover_icon' + db.add_column('chimere_subcategory', 'hover_icon', + self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='subcat_hovered', null=True, to=orm['chimere.Icon']), + keep_default=False) + + # Adding field 'SubCategory.as_layer' + db.add_column('chimere_subcategory', 'as_layer', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'SubCategory.routing_warn' + db.add_column('chimere_subcategory', 'routing_warn', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'News.is_front_page' + db.add_column('chimere_news', 'is_front_page', + self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True), + keep_default=False) + + # Adding field 'News.url' + db.add_column('chimere_news', 'url', + self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True), + keep_default=False) + + # Adding field 'Marker.is_front_page' + db.add_column('chimere_marker', 'is_front_page', + self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting model 'PropertyModelChoice' + db.delete_table('chimere_propertymodelchoice') + + # Deleting model 'Page' + db.delete_table('chimere_page') + + # Deleting field 'SubCategory.dated' + db.delete_column('chimere_subcategory', 'dated') + + # Deleting field 'SubCategory.description' + db.delete_column('chimere_subcategory', 'description') + + # Deleting field 'SubCategory.hover_icon' + db.delete_column('chimere_subcategory', 'hover_icon_id') + + # Deleting field 'SubCategory.as_layer' + db.delete_column('chimere_subcategory', 'as_layer') + + # Deleting field 'SubCategory.routing_warn' + db.delete_column('chimere_subcategory', 'routing_warn') + + # Deleting field 'News.is_front_page' + db.delete_column('chimere_news', 'is_front_page') + + # Deleting field 'News.url' + db.delete_column('chimere_news', 'url') + + # Deleting field 'Marker.is_front_page' + db.delete_column('chimere_marker', 'is_front_page') + + + models = { + 'chimere.aggregatedroute': { + 'Meta': {'object_name': 'AggregatedRoute', 'db_table': "'chimere_aggregated_routes'", 'managed': 'False'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'route': ('django.contrib.gis.db.models.fields.MultiLineStringField', [], {}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"}) + }, + '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_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + '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'}), + 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'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'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.page': { + 'Meta': {'object_name': 'Page'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'content': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mnemonic': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '10', 'null': 'True', 'blank': 'True'}), + 'template_path': ('django.db.models.fields.CharField', [], {'max_length': '150', 'null': 'True', 'blank': '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.propertymodelchoice': { + 'Meta': {'object_name': 'PropertyModelChoice'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': "orm['chimere.PropertyModel']"}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + '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'}, + 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'hover_icon': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subcat_hovered'", 'null': 'True', 'to': "orm['chimere.Icon']"}), + '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'}), + 'routing_warn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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/migrations/0003_create_aggregate_route_view.py b/chimere/migrations/0003_create_aggregate_route_view.py new file mode 100644 index 0000000..ca32eb6 --- /dev/null +++ b/chimere/migrations/0003_create_aggregate_route_view.py @@ -0,0 +1,290 @@ +# -*- 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): + sql = """ + create view chimere_aggregated_routes (id, subcategory_id, status, route) as + SELECT row_number() + OVER (ORDER BY "chimere_route_categories"."subcategory_id", + "chimere_route"."status"), + "chimere_route_categories"."subcategory_id", "chimere_route"."status", + ST_Multi(ST_Collect("chimere_route"."route")) FROM "chimere_route" + LEFT OUTER JOIN "chimere_route_categories" ON ( + "chimere_route"."id" = "chimere_route_categories"."route_id") + WHERE ("chimere_route"."start_date" IS NULL + OR ("chimere_route"."start_date" <= CURRENT_DATE + AND "chimere_route"."start_date" >= CURRENT_DATE) + OR ("chimere_route"."start_date" <= CURRENT_DATE + AND "chimere_route"."end_date" >= CURRENT_DATE)) + GROUP BY "chimere_route_categories"."subcategory_id", + "chimere_route"."status"; + """ + db.execute(sql) + + def backwards(self, orm): + sql = "drop view chimere_aggregated_routes;" + db.execute(sql) + + models = { + 'chimere.aggregatedroute': { + 'Meta': {'object_name': 'AggregatedRoute', 'db_table': "'chimere_aggregated_routes'", 'managed': 'False'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'route': ('django.contrib.gis.db.models.fields.MultiLineStringField', [], {}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"}) + }, + '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_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + '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'}), + 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'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'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.page': { + 'Meta': {'object_name': 'Page'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'content': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mnemonic': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '10', 'null': 'True', 'blank': 'True'}), + 'template_path': ('django.db.models.fields.CharField', [], {'max_length': '150', 'null': 'True', 'blank': '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.propertymodelchoice': { + 'Meta': {'object_name': 'PropertyModelChoice'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': "orm['chimere.PropertyModel']"}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + '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'}, + 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'}), + 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'hover_icon': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subcat_hovered'", 'null': 'True', 'to': "orm['chimere.Icon']"}), + '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'}), + 'routing_warn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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'] diff --git a/chimere/models.py b/chimere/models.py index 25bc708..545d7e0 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,6 +25,8 @@ import simplejson as json from lxml import etree from PIL import Image from subprocess import Popen, PIPE +from BeautifulSoup import BeautifulSoup + from django import forms from django.conf import settings from django.contrib import admin @@ -45,13 +47,64 @@ from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager, \ GeoRSSManager, CSVManager +class Page(models.Model): + """Simple extra pages + """ + title = models.CharField(_(u"Name"), max_length=150) + mnemonic = models.CharField(_(u"Mnemonic"), max_length=10, blank=True, + null=True) + available = models.BooleanField(_(u"Available"), default=True) + order = models.IntegerField(_(u"Order"), default=10, blank=True, null=True) + template_path = models.CharField(_(u"Template path"), max_length=150, + blank=True, null=True) + content = models.TextField(blank=True, null=True) + def __unicode__(self): + ordering = ["order"] + return self.title + class Meta: + verbose_name = _(u"Page") + verbose_name_plural = _(u"Page") + +def page_post_save(sender, **kwargs): + if not kwargs['instance']: + return + page = kwargs['instance'] + if not page.mnemonic: + page.mnemonic = defaultfilters.slugify(page.title) + page.save() +post_save.connect(page_post_save, sender=Page) + +def shortify(text): + if not text: + return '' + if len(text) <= settings.CHIMERE_SHORT_DESC_LENGTH: + return text + desc = text[:settings.CHIMERE_SHORT_DESC_LENGTH] + short_desc = "" + # find a correct opportunity to cut + for idx, c in enumerate(reversed(desc)): + if c == '>': + break + if c == '<': + short_desc = desc[:-(idx+1)] + break + if not short_desc: + for idx, c in enumerate(reversed(desc)): + if c == ' ' or c == '\n': + short_desc = desc[:-(idx+1)] + break + return BeautifulSoup(short_desc).prettify() + class News(models.Model): """News of the site """ title = models.CharField(_(u"Name"), max_length=150) available = models.BooleanField(_(u"Available")) + is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True, + null=True) date = models.DateField(_(u"Date"), auto_now_add=True) content = models.TextField() + url = models.URLField(_(u"Url"), max_length=200, blank=True, null=True) areas = SelectMultipleField('Area', verbose_name=_(u"Associated areas"), blank=True, null=True) def __unicode__(self): @@ -61,6 +114,10 @@ class News(models.Model): verbose_name = _(u"News") verbose_name_plural = _(u"News") + @property + def short_desc(self): + return shortify(self.content) + class TinyUrl(models.Model): """Tinyfied version of permalink parameters """ @@ -156,14 +213,21 @@ class SubCategory(models.Model): available = models.BooleanField(_(u"Available"), default=True) submission = models.BooleanField(_(u"Available for submission"), default=True) - icon = models.ForeignKey(Icon, verbose_name=_(u"Icon")) - color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"), - blank=True, null=True) - order = models.IntegerField(_(u"Order"), default=1000) TYPE = (('M', _(u'Marker')), ('R', _(u'Route')), ('B', _(u'Both')),) item_type = models.CharField(_(u"Item type"), max_length=1, choices=TYPE) + dated = models.BooleanField(_(u"Is dated"), default=False) + description = models.TextField(blank=True, null=True) + icon = models.ForeignKey(Icon, verbose_name=_(u"Icon")) + hover_icon = models.ForeignKey(Icon, verbose_name=_(u"Hover icon"), + blank=True, null=True, related_name='subcat_hovered') + color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"), + blank=True, null=True) + as_layer = models.BooleanField(_(u"Displayed in the layer menu"), + default=False) + routing_warn = models.BooleanField(_(u"Routing warn"), default=False) + order = models.IntegerField(_(u"Order"), default=1000) def __unicode__(self): return u"%s / %s" % (self.category.name, self.name) class Meta: @@ -207,6 +271,32 @@ class SubCategory(models.Model): subcategories = sorted(subcategories, key=get_cat_order) return subcategories + @classmethod + def getAvailableTuples(cls, area_name=None): + cats = [] + for cat, subcats in cls.getAvailable(area_name=area_name): + cats.append((unicode(cat), + [(subcat.pk, subcat.name) for subcat in subcats])) + return cats + + def getJSONDict(self): + items = {'id':self.pk, 'name':self.name, + 'description':self.description if self.description\ + else '', + 'icon':{'url':self.icon.image.url, + 'width':self.icon.image.width, + 'height':self.icon.image.height} + } + if self.hover_icon: + items['icon_hover'] = {'url':self.hover_icon.image.url} + return items + + def getJSON(self, categories_id=[]): + '''Return a JSON string - mainly used to get description + ''' + json_string = json.dumps(self.getJSONDict()) + return json_string + IMPORTERS = {'KML':KMLManager, 'OSM':OSMManager, 'SHP':ShapefileManager, @@ -274,6 +364,13 @@ class Importer(models.Model): def display_categories(self): return u"\n".join([cat.name for cat in self.categories.all()]) +STATUS = (('S', _(u'Submited')), + ('A', _(u'Available')), + ('M', _(u'Modified')), + ('D', _(u'Disabled')), + ('I', _(u'Imported'))) +STATUS_DCT = dict(STATUS) + class GeographicItem(models.Model): name = models.CharField(_(u"Name"), max_length=150) categories = SelectMultipleField(SubCategory) @@ -285,12 +382,6 @@ class GeographicItem(models.Model): null=True) submiter_comment = models.TextField(_(u"Submitter comment"), max_length=200, blank=True, null=True) - STATUS = (('S', _(u'Submited')), - ('A', _(u'Available')), - ('M', _(u'Modified')), - ('D', _(u'Disabled')), - ('I', _(u'Imported'))) - STATUS_DCT = dict(STATUS) status = models.CharField(_(u"Status"), max_length=1, choices=STATUS) import_key = models.CharField(_(u"Import key"), max_length=200, blank=True, null=True) @@ -349,6 +440,10 @@ class GeographicItem(models.Model): def properties(cls): return [pm for pm in PropertyModel.objects.filter(available=True)] + @classmethod + def all_properties(cls): + return [pm for pm in PropertyModel.objects.all()] + def property_setter(cls, propertymodel): def setter(self, value): marker = self @@ -371,6 +466,8 @@ class Marker(GeographicItem): route = models.ForeignKey(u"Route", blank=True, null=True, related_name='associated_marker') description = models.TextField(_(u"Description"), blank=True, null=True) + is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True, + null=True) objects = models.GeoManager() def __unicode__(self): @@ -379,7 +476,7 @@ class Marker(GeographicItem): def __init__(self, *args, **kwargs): super(Marker, self).__init__(*args, **kwargs) # add read attributes for properties - for pm in self.properties(): + for pm in self.all_properties(): attr_name = pm.getAttrName() if not hasattr(self, attr_name): val = '' @@ -426,6 +523,10 @@ class Marker(GeographicItem): return self.start_date @property + def short_desc(self): + return shortify(self.description) + + @property def geometry(self): return self.point.wkt @@ -481,6 +582,18 @@ class Marker(GeographicItem): if len(properties) > 1: for property in properties[1:]: property.delete() + if pm.type == 'C' and value: + try: + value = str(int(value)) + except ValueError: + choice = PropertyModelChoice.objects.filter(propertymodel=pm, + value=value) + if choice.count(): + value = choice.all()[0].pk + else: + choice = PropertyModelChoice.objects.create(value=value, + propertymodel=pm) + value = choice.pk # new property if not properties: new_property = Property.objects.create(marker=self, @@ -512,12 +625,18 @@ class Marker(GeographicItem): items = {'id':self.id, 'name':json.dumps(self.name), 'geometry':self.point.geojson, 'icon_path':cat.icon.image, + 'icon_hover_path':cat.hover_icon.image \ + if cat.hover_icon else '', 'icon_width':cat.icon.image.width, - 'icon_height':cat.icon.image.height,} + 'icon_height':cat.icon.image.height, + 'category_name':json.dumps(cat.name)} jsons.append(u'{"type":"Feature", "geometry":%(geometry)s, '\ u'"properties":{"pk": %(id)d, "name": %(name)s, '\ - u'"icon_path":"%(icon_path)s", "icon_width":%(icon_width)d, '\ - u'"icon_height":%(icon_height)d}}' % items) + u'"icon_path":"%(icon_path)s", '\ + u'"icon_hover_path":"%(icon_hover_path)s", '\ + u'"icon_width":%(icon_width)d, '\ + u'"icon_height":%(icon_height)d, '\ + u'"category_name":%(category_name)s}}' % items) return ",".join(jsons) @property @@ -1067,6 +1186,28 @@ def getDateCondition(): date_condition += "%(alias)s.end_date >='" + now + "')) " return date_condition +class AggregatedRoute(models.Model): + ''' + Database view for aggregated routes + ''' + route = models.MultiLineStringField() + subcategory = models.ForeignKey(SubCategory) + status = models.CharField(_(u"Status"), max_length=1, choices=STATUS) + class Meta: + managed = False + db_table = 'chimere_aggregated_routes' + + def getGeoJSON(self, color="#000"): + '''Return a GeoJSON string + ''' + if '#' not in color: + color = '#' + color + attributes = {'id':self.id, 'name':json.dumps(u'Aggregated route'), + 'color':color, 'geometry':self.route.geojson,} + return u'{"type":"Feature", "geometry":%(geometry)s, '\ + u'"properties":{"pk": %(id)d, "name": %(name)s, '\ + u'"color":"%(color)s"}}' % attributes + class SimplePoint: """ Point in the map (not in the database) @@ -1357,11 +1498,15 @@ class PropertyModel(models.Model): TYPE = (('T', _('Text')), ('L', _('Long text')), ('P', _('Password')), - ('D', _("Date"))) + ('D', _("Date")), + ('C', _("Choices")), + ) TYPE_WIDGET = {'T':forms.TextInput, 'L':TextareaWidget, 'P':forms.PasswordInput, - 'D':DatePickerWidget} + 'D':DatePickerWidget, + 'C':forms.Select + } type = models.CharField(_(u"Type"), max_length=1, choices=TYPE) def __unicode__(self): return self.name @@ -1379,6 +1524,19 @@ class PropertyModel(models.Model): ''' return 'property_%d_%d' % (self.order, self.id) +class PropertyModelChoice(models.Model): + '''Choices for property model + ''' + propertymodel = models.ForeignKey(PropertyModel, related_name='choices', + verbose_name=_(u"Property model")) + value = models.CharField(_(u"Value"), max_length=150) + available = models.BooleanField(_(u"Available"), default=True) + def __unicode__(self): + return unicode(self.value) + + class Meta: + verbose_name = _(u"Model property choice") + class Property(models.Model): '''Property for a POI ''' @@ -1387,7 +1545,14 @@ class Property(models.Model): verbose_name=_(u"Property model")) value = models.TextField(_(u"Value")) def __unicode__(self): - return "%s : %s" % (str(self.propertymodel), self.value) + if self.propertymodel.type == 'C': + try: + return unicode(PropertyModelChoice.objects.get( + pk=self.value).value) + except self.DoesNotExist: + return "" + return unicode(self.value) + class Meta: verbose_name = _(u"Property") @@ -1398,6 +1563,11 @@ class Property(models.Model): return datetime.date(*[int(val) for val in self.value.split('-')]) except: return "" + if self.propertymodel.type == 'C' and self.value: + try: + return PropertyModelChoice.objects.get(pk=self.value) + except self.DoesNotExist: + return None else: return self.value diff --git a/chimere/old_migrations/v2.0/0001_initial.py b/chimere/old_migrations/v2.0/0001_initial.py new file mode 100644 index 0000000..74f67a6 --- /dev/null +++ b/chimere/old_migrations/v2.0/0001_initial.py @@ -0,0 +1,342 @@ +# encoding: 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 'News' + db.create_table('main_news', ( + ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('date', self.gf('django.db.models.fields.DateField')(auto_now_add=True, blank=True)), + ('content', self.gf('django.db.models.fields.TextField')()), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['News']) + + # Adding model 'TinyUrl' + db.create_table('main_tinyurl', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('parameters', self.gf('django.db.models.fields.CharField')(max_length=500)), + )) + db.send_create_signal('chimere', ['TinyUrl']) + + # Adding model 'ColorTheme' + db.create_table('main_colortheme', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['ColorTheme']) + + # Adding model 'Color' + db.create_table('main_color', ( + ('code', self.gf('django.db.models.fields.CharField')(max_length=6)), + ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + )) + db.send_create_signal('chimere', ['Color']) + + # Adding model 'Category' + db.create_table('main_category', ( + ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['Category']) + + # Adding model 'Icon' + db.create_table('main_icon', ( + ('width', self.gf('django.db.models.fields.IntegerField')()), + ('image', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), + ('height', self.gf('django.db.models.fields.IntegerField')()), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['Icon']) + + # Adding model 'SubCategory' + db.create_table('main_subcategory', ( + ('category', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Category'])), + ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('item_type', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('color_theme', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.ColorTheme'], null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('icon', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Icon'])), + )) + db.send_create_signal('chimere', ['SubCategory']) + + # Adding M2M table for field areas on 'SubCategory' + db.create_table('main_subcategory_areas', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)), + ('area', models.ForeignKey(orm['chimere.area'], null=False)) + )) + db.create_unique('main_subcategory_areas', ['subcategory_id', 'area_id']) + + # Adding model 'Marker' + db.create_table('main_marker', ( + ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('end_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('point', self.gf('chimere.widgets.PointField')()), + ('route', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Route'], null=True, blank=True)), + ('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('available_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('chimere', ['Marker']) + + # Adding M2M table for field categories on 'Marker' + db.create_table('main_marker_categories', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('marker', models.ForeignKey(orm['chimere.marker'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) + )) + db.create_unique('main_marker_categories', ['marker_id', 'subcategory_id']) + + # Adding model 'RouteFile' + db.create_table('main_routefile', ( + ('file_type', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('raw_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)), + ('simplified_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['RouteFile']) + + # Adding model 'Route' + db.create_table('main_route', ( + ('status', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('end_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('route', self.gf('chimere.widgets.RouteField')()), + ('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('associated_file', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.RouteFile'], null=True, blank=True)), + ('start_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('chimere', ['Route']) + + # Adding M2M table for field categories on 'Route' + db.create_table('main_route_categories', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('route', models.ForeignKey(orm['chimere.route'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) + )) + db.create_unique('main_route_categories', ['route_id', 'subcategory_id']) + + # Adding model 'Area' + db.create_table('main_area', ( + ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + ('urn', self.gf('django.db.models.fields.SlugField')(db_index=True, unique=True, max_length=50, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('upper_left_corner', self.gf('django.contrib.gis.db.models.fields.PointField')(default='POINT(0 0)')), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('lower_right_corner', self.gf('django.contrib.gis.db.models.fields.PointField')(default='POINT(0 0)')), + )) + db.send_create_signal('chimere', ['Area']) + + # Adding model 'PropertyModel' + db.create_table('main_propertymodel', ( + ('available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('order', self.gf('django.db.models.fields.IntegerField')()), + ('type', self.gf('django.db.models.fields.CharField')(max_length=1)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=150)), + )) + db.send_create_signal('chimere', ['PropertyModel']) + + # Adding model 'Property' + db.create_table('main_property', ( + ('marker', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.Marker'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('value', self.gf('django.db.models.fields.TextField')()), + ('propertymodel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.PropertyModel'])), + )) + db.send_create_signal('chimere', ['Property']) + + + def backwards(self, orm): + + # Deleting model 'News' + db.delete_table('main_news') + + # Deleting model 'TinyUrl' + db.delete_table('main_tinyurl') + + # Deleting model 'ColorTheme' + db.delete_table('main_colortheme') + + # Deleting model 'Color' + db.delete_table('main_color') + + # Deleting model 'Category' + db.delete_table('main_category') + + # Deleting model 'Icon' + db.delete_table('main_icon') + + # Deleting model 'SubCategory' + db.delete_table('main_subcategory') + + # Removing M2M table for field areas on 'SubCategory' + db.delete_table('main_subcategory_areas') + + # Deleting model 'Marker' + db.delete_table('main_marker') + + # Removing M2M table for field categories on 'Marker' + db.delete_table('main_marker_categories') + + # Deleting model 'RouteFile' + db.delete_table('main_routefile') + + # Deleting model 'Route' + db.delete_table('main_route') + + # Removing M2M table for field categories on 'Route' + db.delete_table('main_route_categories') + + # Deleting model 'Area' + db.delete_table('main_area') + + # Deleting model 'PropertyModel' + db.delete_table('main_propertymodel') + + # Deleting model 'Property' + db.delete_table('main_property') + + + models = { + 'chimere.area': { + 'Meta': {'object_name': 'Area', 'db_table': "'main_area'"}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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', [], {}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'unique': 'True', 'max_length': '50', 'blank': 'True'}) + }, + 'chimere.category': { + 'Meta': {'object_name': 'Category', 'db_table': "'main_category'"}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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': {'object_name': 'Color', 'db_table': "'main_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', 'db_table': "'main_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', 'db_table': "'main_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.marker': { + 'Meta': {'object_name': 'Marker', 'db_table': "'main_marker'"}, + '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'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'point': ('chimere.widgets.PointField', [], {}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Route']", 'null': 'True', 'blank': 'True'}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News', 'db_table': "'main_news'"}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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.property': { + 'Meta': {'object_name': 'Property', 'db_table': "'main_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': {'object_name': 'PropertyModel', 'db_table': "'main_propertymodel'"}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', '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', [], {}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '1'}) + }, + 'chimere.route': { + 'Meta': {'object_name': 'Route', 'db_table': "'main_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'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'object_name': 'RouteFile', 'db_table': "'main_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': {'object_name': 'SubCategory', 'db_table': "'main_subcategory'"}, + 'areas': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'to': "orm['chimere.Area']"}), + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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', 'db_table': "'main_tinyurl'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] diff --git a/chimere/migrations/0002_rename_models.py b/chimere/old_migrations/v2.0/0002_rename_models.py index 32aabc7..32aabc7 100644 --- a/chimere/migrations/0002_rename_models.py +++ b/chimere/old_migrations/v2.0/0002_rename_models.py diff --git a/chimere/migrations/0003_auto__add_field_route_submiter_session_key__add_field_route_submiter_e.py b/chimere/old_migrations/v2.0/0003_auto__add_field_route_submiter_session_key__add_field_route_submiter_e.py index 11ce001..11ce001 100644 --- a/chimere/migrations/0003_auto__add_field_route_submiter_session_key__add_field_route_submiter_e.py +++ b/chimere/old_migrations/v2.0/0003_auto__add_field_route_submiter_session_key__add_field_route_submiter_e.py diff --git a/chimere/migrations/0004_auto__add_picturefile__add_multimediafile.py b/chimere/old_migrations/v2.0/0004_auto__add_picturefile__add_multimediafile.py index cfa1db0..cfa1db0 100644 --- a/chimere/migrations/0004_auto__add_picturefile__add_multimediafile.py +++ b/chimere/old_migrations/v2.0/0004_auto__add_picturefile__add_multimediafile.py diff --git a/chimere/migrations/0005_auto__add_multimediatype__add_field_picturefile_order__del_field_multi.py b/chimere/old_migrations/v2.0/0005_auto__add_multimediatype__add_field_picturefile_order__del_field_multi.py index fd7a86b..fd7a86b 100644 --- a/chimere/migrations/0005_auto__add_multimediatype__add_field_picturefile_order__del_field_multi.py +++ b/chimere/old_migrations/v2.0/0005_auto__add_multimediatype__add_field_picturefile_order__del_field_multi.py diff --git a/chimere/migrations/0006_auto__add_importer__add_field_route_import_key__add_field_marker_impor.py b/chimere/old_migrations/v2.0/0006_auto__add_importer__add_field_route_import_key__add_field_marker_impor.py index 3157039..3157039 100644 --- a/chimere/migrations/0006_auto__add_importer__add_field_route_import_key__add_field_marker_impor.py +++ b/chimere/old_migrations/v2.0/0006_auto__add_importer__add_field_route_import_key__add_field_marker_impor.py diff --git a/chimere/migrations/0007_auto__add_field_marker_description.py b/chimere/old_migrations/v2.0/0007_auto__add_field_marker_description.py index 99382d5..99382d5 100644 --- a/chimere/migrations/0007_auto__add_field_marker_description.py +++ b/chimere/old_migrations/v2.0/0007_auto__add_field_marker_description.py diff --git a/chimere/migrations/0008_auto__del_field_importer_subcategory__add_field_route_import_source__a.py b/chimere/old_migrations/v2.0/0008_auto__del_field_importer_subcategory__add_field_route_import_source__a.py index c40b027..c40b027 100644 --- a/chimere/migrations/0008_auto__del_field_importer_subcategory__add_field_route_import_source__a.py +++ b/chimere/old_migrations/v2.0/0008_auto__del_field_importer_subcategory__add_field_route_import_source__a.py diff --git a/chimere/migrations/0009_auto__add_field_importer_state.py b/chimere/old_migrations/v2.0/0009_auto__add_field_importer_state.py index 42d1048..42d1048 100644 --- a/chimere/migrations/0009_auto__add_field_importer_state.py +++ b/chimere/old_migrations/v2.0/0009_auto__add_field_importer_state.py diff --git a/chimere/migrations/0010_auto__add_field_route_import_version__add_field_marker_import_version.py b/chimere/old_migrations/v2.0/0010_auto__add_field_route_import_version__add_field_marker_import_version.py index c94710f..c94710f 100644 --- a/chimere/migrations/0010_auto__add_field_route_import_version__add_field_marker_import_version.py +++ b/chimere/old_migrations/v2.0/0010_auto__add_field_route_import_version__add_field_marker_import_version.py diff --git a/chimere/migrations/0011_auto__del_field_importer_source_url__add_field_importer_source.py b/chimere/old_migrations/v2.0/0011_auto__del_field_importer_source_url__add_field_importer_source.py index 31ce4d8..31ce4d8 100644 --- a/chimere/migrations/0011_auto__del_field_importer_source_url__add_field_importer_source.py +++ b/chimere/old_migrations/v2.0/0011_auto__del_field_importer_source_url__add_field_importer_source.py diff --git a/chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py b/chimere/old_migrations/v2.0/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py index fc6007c..fc6007c 100644 --- a/chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py +++ b/chimere/old_migrations/v2.0/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py diff --git a/chimere/migrations/0013_auto__add_field_multimediafile_miniature.py b/chimere/old_migrations/v2.0/0013_auto__add_field_multimediafile_miniature.py index bc9e003..bc9e003 100644 --- a/chimere/migrations/0013_auto__add_field_multimediafile_miniature.py +++ b/chimere/old_migrations/v2.0/0013_auto__add_field_multimediafile_miniature.py diff --git a/chimere/migrations/0014_auto__add_field_picturefile_marker__add_field_multimediafile_marker__a.py b/chimere/old_migrations/v2.0/0014_auto__add_field_picturefile_marker__add_field_multimediafile_marker__a.py index 5c059fd..5c059fd 100644 --- a/chimere/migrations/0014_auto__add_field_picturefile_marker__add_field_multimediafile_marker__a.py +++ b/chimere/old_migrations/v2.0/0014_auto__add_field_picturefile_marker__add_field_multimediafile_marker__a.py diff --git a/chimere/migrations/0015_auto__chg_field_picturefile_marker__chg_field_multimediafile_marker.py b/chimere/old_migrations/v2.0/0015_auto__chg_field_picturefile_marker__chg_field_multimediafile_marker.py index 83c7535..83c7535 100644 --- a/chimere/migrations/0015_auto__chg_field_picturefile_marker__chg_field_multimediafile_marker.py +++ b/chimere/old_migrations/v2.0/0015_auto__chg_field_picturefile_marker__chg_field_multimediafile_marker.py diff --git a/chimere/migrations/0016_auto__add_field_importer_zipped.py b/chimere/old_migrations/v2.0/0016_auto__add_field_importer_zipped.py index 9df4d91..9df4d91 100644 --- a/chimere/migrations/0016_auto__add_field_importer_zipped.py +++ b/chimere/old_migrations/v2.0/0016_auto__add_field_importer_zipped.py diff --git a/chimere/migrations/0017_auto__add_field_importer_srid.py b/chimere/old_migrations/v2.0/0017_auto__add_field_importer_srid.py index 378da72..378da72 100644 --- a/chimere/migrations/0017_auto__add_field_importer_srid.py +++ b/chimere/old_migrations/v2.0/0017_auto__add_field_importer_srid.py diff --git a/chimere/migrations/0018_auto__add_layer__add_arealayers.py b/chimere/old_migrations/v2.0/0018_auto__add_layer__add_arealayers.py index 0ea2062..0ea2062 100644 --- a/chimere/migrations/0018_auto__add_layer__add_arealayers.py +++ b/chimere/old_migrations/v2.0/0018_auto__add_layer__add_arealayers.py diff --git a/chimere/migrations/0019_auto__chg_field_layer_layer_code__add_field_area_welcome_message.py b/chimere/old_migrations/v2.0/0019_auto__chg_field_layer_layer_code__add_field_area_welcome_message.py index d6475c1..d6475c1 100644 --- a/chimere/migrations/0019_auto__chg_field_layer_layer_code__add_field_area_welcome_message.py +++ b/chimere/old_migrations/v2.0/0019_auto__chg_field_layer_layer_code__add_field_area_welcome_message.py diff --git a/chimere/migrations/0020_auto.py b/chimere/old_migrations/v2.0/0020_auto.py index e7f4d70..e7f4d70 100644 --- a/chimere/migrations/0020_auto.py +++ b/chimere/old_migrations/v2.0/0020_auto.py diff --git a/chimere/migrations/0021_auto.py b/chimere/old_migrations/v2.0/0021_auto.py index 9193147..9193147 100644 --- a/chimere/migrations/0021_auto.py +++ b/chimere/old_migrations/v2.0/0021_auto.py diff --git a/chimere/migrations/0022_auto__add_field_area_external_css.py b/chimere/old_migrations/v2.0/0022_auto__add_field_area_external_css.py index 206b6d8..206b6d8 100644 --- a/chimere/migrations/0022_auto__add_field_area_external_css.py +++ b/chimere/old_migrations/v2.0/0022_auto__add_field_area_external_css.py diff --git a/chimere/migrations/0023_auto__add_field_area_restrict_to_extent.py b/chimere/old_migrations/v2.0/0023_auto__add_field_area_restrict_to_extent.py index 742793c..742793c 100644 --- a/chimere/migrations/0023_auto__add_field_area_restrict_to_extent.py +++ b/chimere/old_migrations/v2.0/0023_auto__add_field_area_restrict_to_extent.py diff --git a/chimere/migrations/0024_auto__add_field_marker_available_date.py b/chimere/old_migrations/v2.0/0024_auto__add_field_marker_available_date.py index 78b5a68..78b5a68 100644 --- a/chimere/migrations/0024_auto__add_field_marker_available_date.py +++ b/chimere/old_migrations/v2.0/0024_auto__add_field_marker_available_date.py diff --git a/chimere/migrations/0025_auto__add_field_area_dynamic_categories.py b/chimere/old_migrations/v2.0/0025_auto__add_field_area_dynamic_categories.py index ac8b62e..ac8b62e 100644 --- a/chimere/migrations/0025_auto__add_field_area_dynamic_categories.py +++ b/chimere/old_migrations/v2.0/0025_auto__add_field_area_dynamic_categories.py diff --git a/chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py b/chimere/old_migrations/v2.0/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py index 9965ec1..9965ec1 100644 --- a/chimere/migrations/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py +++ b/chimere/old_migrations/v2.0/0026_auto__add_field_marker_submiter_name__add_field_route_submiter_name.py diff --git a/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py b/chimere/old_migrations/v2.0/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py index 53ee3d4..53ee3d4 100644 --- a/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py +++ b/chimere/old_migrations/v2.0/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py diff --git a/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py b/chimere/old_migrations/v2.0/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py index 2f81645..2f81645 100644 --- a/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py +++ b/chimere/old_migrations/v2.0/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py diff --git a/chimere/migrations/0029_auto__add_field_marker_modified_since_import__add_field_marker_not_for.py b/chimere/old_migrations/v2.0/0029_auto__add_field_marker_modified_since_import__add_field_marker_not_for.py index 72d718c..72d718c 100644 --- a/chimere/migrations/0029_auto__add_field_marker_modified_since_import__add_field_marker_not_for.py +++ b/chimere/old_migrations/v2.0/0029_auto__add_field_marker_modified_since_import__add_field_marker_not_for.py diff --git a/chimere/migrations/0030_auto__add_field_importer_default_name.py b/chimere/old_migrations/v2.0/0030_auto__add_field_importer_default_name.py index b43d44c..b43d44c 100644 --- a/chimere/migrations/0030_auto__add_field_importer_default_name.py +++ b/chimere/old_migrations/v2.0/0030_auto__add_field_importer_default_name.py diff --git a/chimere/migrations/0031_auto__chg_field_picturefile_width__chg_field_picturefile_height.py b/chimere/old_migrations/v2.0/0031_auto__chg_field_picturefile_width__chg_field_picturefile_height.py index dac7145..dac7145 100644 --- a/chimere/migrations/0031_auto__chg_field_picturefile_width__chg_field_picturefile_height.py +++ b/chimere/old_migrations/v2.0/0031_auto__chg_field_picturefile_width__chg_field_picturefile_height.py diff --git a/chimere/migrations/0032_auto__add_field_subcategory_submission.py b/chimere/old_migrations/v2.0/0032_auto__add_field_subcategory_submission.py index d96e5bb..d96e5bb 100644 --- a/chimere/migrations/0032_auto__add_field_subcategory_submission.py +++ b/chimere/old_migrations/v2.0/0032_auto__add_field_subcategory_submission.py diff --git a/chimere/migrations/0033_auto__add_field_importer_source_file.py b/chimere/old_migrations/v2.0/0033_auto__add_field_importer_source_file.py index 788d12c..788d12c 100644 --- a/chimere/migrations/0033_auto__add_field_importer_source_file.py +++ b/chimere/old_migrations/v2.0/0033_auto__add_field_importer_source_file.py diff --git a/chimere/migrations/0034_auto__add_field_importer_origin__add_field_importer_license__add_field.py b/chimere/old_migrations/v2.0/0034_auto__add_field_importer_origin__add_field_importer_license__add_field.py index 757deab..757deab 100644 --- a/chimere/migrations/0034_auto__add_field_importer_origin__add_field_importer_license__add_field.py +++ b/chimere/old_migrations/v2.0/0034_auto__add_field_importer_origin__add_field_importer_license__add_field.py diff --git a/chimere/migrations/0035_area_permissions.py b/chimere/old_migrations/v2.0/0035_area_permissions.py index d396050..d396050 100644 --- a/chimere/migrations/0035_area_permissions.py +++ b/chimere/old_migrations/v2.0/0035_area_permissions.py diff --git a/chimere/migrations/0036_auto.py b/chimere/old_migrations/v2.0/0036_auto.py index bb93496..bb93496 100644 --- a/chimere/migrations/0036_auto.py +++ b/chimere/old_migrations/v2.0/0036_auto.py diff --git a/chimere/migrations/0037_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py b/chimere/old_migrations/v2.0/0037_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py index 5269e8b..5269e8b 100644 --- a/chimere/migrations/0037_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py +++ b/chimere/old_migrations/v2.0/0037_auto__add_unique_area_order__add_field_importer_associate_marker_to_wa.py diff --git a/chimere/migrations/0038_osm_import_filtr.py b/chimere/old_migrations/v2.0/0038_osm_import_filtr.py index 2b8666b..2b8666b 100644 --- a/chimere/migrations/0038_osm_import_filtr.py +++ b/chimere/old_migrations/v2.0/0038_osm_import_filtr.py diff --git a/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py b/chimere/old_migrations/v2.0/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py index 0b26a27..0b26a27 100644 --- a/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py +++ b/chimere/old_migrations/v2.0/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py diff --git a/chimere/migrations/0040_remove_excluded_status.py b/chimere/old_migrations/v2.0/0040_remove_excluded_status.py index 3fda56b..3fda56b 100644 --- a/chimere/migrations/0040_remove_excluded_status.py +++ b/chimere/old_migrations/v2.0/0040_remove_excluded_status.py diff --git a/chimere/migrations/0041_auto__add_field_importer_overwrite.py b/chimere/old_migrations/v2.0/0041_auto__add_field_importer_overwrite.py index 9ae6b84..9ae6b84 100644 --- a/chimere/migrations/0041_auto__add_field_importer_overwrite.py +++ b/chimere/old_migrations/v2.0/0041_auto__add_field_importer_overwrite.py diff --git a/chimere/migrations/0042_fix_rights.py b/chimere/old_migrations/v2.0/0042_fix_rights.py index 6b64313..6b64313 100644 --- a/chimere/migrations/0042_fix_rights.py +++ b/chimere/old_migrations/v2.0/0042_fix_rights.py diff --git a/chimere/migrations/0043_auto__add_field_importer_get_description.py b/chimere/old_migrations/v2.0/0043_auto__add_field_importer_get_description.py index 295d3b2..295d3b2 100644 --- a/chimere/migrations/0043_auto__add_field_importer_get_description.py +++ b/chimere/old_migrations/v2.0/0043_auto__add_field_importer_get_description.py diff --git a/chimere/migrations/0044_auto__add_field_importer_default_description.py b/chimere/old_migrations/v2.0/0044_auto__add_field_importer_default_description.py index ccabcd4..ccabcd4 100644 --- a/chimere/migrations/0044_auto__add_field_importer_default_description.py +++ b/chimere/old_migrations/v2.0/0044_auto__add_field_importer_default_description.py diff --git a/chimere/old_migrations/v2.0/__init__.py b/chimere/old_migrations/v2.0/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chimere/old_migrations/v2.0/__init__.py diff --git a/chimere/route.py b/chimere/route.py new file mode 100644 index 0000000..8c4638a --- /dev/null +++ b/chimere/route.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +""" +Routing management +""" + +import os, re, shutil, tempfile +from BeautifulSoup import BeautifulSoup +from subprocess import Popen, PIPE +from django.contrib.gis.gdal import DataSource +from django.contrib.gis.gdal.error import OGRException + +from django.conf import settings + +class Router: + def route(self, lon1, lat1, lon2, lat2, transport='foot'): + ''' + Get a list of geojson polylines + ''' + return [] + +class RoutinoRouter(Router): + re_desc = [re.compile("<tr class='n'>"), re.compile("<tr class='s'>"), + re.compile("<tr class='t'>")] + def route(self, lon1, lat1, lon2, lat2, steps=[], transport='foot', + speed=None): + ''' + Get a list of geojson polylines and route description + ''' + language = settings.LANGUAGE_CODE.split('-')[0] + args = [settings.CHIMERE_ROUTING_ENGINE['PATH'], + "--dir=%s" % settings.CHIMERE_ROUTING_ENGINE['DB_PATH'], + "--transport=%s" % transport, + "--language=%s" % language, + "--shortest", + "--output-html", + "--output-gpx-track", + "--lat1=%0.15f" % lat1, + "--lon1=%0.15f" % lon1, + ] + if speed: + args += ["--speed-%s=%s" % (highway, unicode(speed)) + for highway in ('motorway', 'trunk', 'primary', 'secondary', + 'tertiary', 'unclassified', 'residential', 'service', + 'track','cycleway','path','steps')] + lonlat_index = 1 + for lon, lat in steps: + lonlat_index += 1 + args += ["--lat%d=%0.15f" % (lonlat_index, lat), + "--lon%d=%0.15f" % (lonlat_index, lon)] + lonlat_index += 1 + args += ["--lat%d=%0.15f" % (lonlat_index, lat2), + "--lon%d=%0.15f" % (lonlat_index, lon2)] + tmp_dir = tempfile.mkdtemp(prefix='chimere_') + os.sep + p = Popen(args, stdout=PIPE, cwd=tmp_dir) + p.communicate() + try: + ds = DataSource(tmp_dir + 'shortest-track.gpx') + except OGRException: + return [], None, None + if not ds: + return [], None, None + layer = ds[0] + trk_layer = None + for layer in ds: + if layer.name == 'tracks': + trk_layer = layer + break + multilines = trk_layer.get_geoms() + res = [] + for multiline in multilines: + res += [geom.geojson for geom in multiline] + desc = [] + # only keeping interessant lines of the desc + for line in open(tmp_dir + 'shortest.html').readlines(): + if [True for r in self.re_desc if r.match(line)]: + desc.append(BeautifulSoup(line).prettify()) + total = self.webify(desc[-1]) + desc = desc[1:-2] + # very fragile piece of code but only break the numerotation + number_tpl = '<tr class="n"><span class="number">%d.</span>' + desc = [re.sub('<tr class="n">', number_tpl % (idx/2+1), d) + if idx % 2 else d + for idx, d in enumerate(desc)] + desc = self.webify(BeautifulSoup('\n'.join(desc)).prettify()) + desc = re.sub(" \[", "", desc) + desc = re.sub(" \]", "", desc) + shutil.rmtree(tmp_dir) + return res, desc, total + + @staticmethod + def webify(lbl): + lbl = re.sub("<td", "<span", lbl) + lbl = re.sub("</td>", "</span>", lbl) + lbl = re.sub("</tr>", "</div>", lbl) + lbl = re.sub("<tr", "<div", lbl) + return lbl + +router = None +if hasattr(settings, 'CHIMERE_ROUTING_ENGINE') and \ + settings.CHIMERE_ROUTING_ENGINE['ENGINE'] == 'routino': + router = RoutinoRouter() + diff --git a/chimere/settings.sample.py b/chimere/settings.sample.py new file mode 100644 index 0000000..bf7c484 --- /dev/null +++ b/chimere/settings.sample.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# This file is an example of settings.py for a Chimère project + +import os +_ = lambda s: s + +DEBUG = False +TEMPLATE_DEBUG = DEBUG + +# Django settings for chimere project. +PROJECT_NAME = 'Chimere' +ROOT_PATH = os.path.realpath(os.path.dirname(__file__)) + "/" + +EMAIL_HOST = 'localhost' +CONTACT_EMAIL = '' +STATIC_URL = '/static/' +STATIC_ROOT = ROOT_PATH + 'static/' + +TINYMCE_URL = '/tinymce/' +JQUERY_JS_URLS = ('/javascript/jquery/jquery.js', + '/javascript/jquery-ui/jquery-ui.js',) +JQUERY_CSS_URLS = ('/javascript/jquery-ui/css/smoothness/jquery-ui.css', + '/javascript/jquery-ui-themes/base/jquery.ui.all.css') + +OSM_CSS_URLS = ["http://www.openlayers.org/api/theme/default/style.css"] + +GPSBABEL = '/usr/bin/gpsbabel' +GPSBABEL_OPTIONS = 'simplify,crosstrack,error=0.005k' # simplify with an + # error of 5 meters +#GPSBABEL_OPTIONS = 'simplify,count=100' + +## chimere specific ## +CHIMERE_DEFAULT_ZOOM = 10 +# center of the map +CHIMERE_DEFAULT_CENTER = (-1.679444, 48.114722) +# projection used by the main map +# most public map providers use spherical mercator : 900913 +CHIMERE_EPSG_PROJECTION = 900913 +# projection displayed to the end user by openlayers +# chimere use the same projection to save its data in the database +CHIMERE_EPSG_DISPLAY_PROJECTION = 4326 +# display of shortcuts for areas +CHIMERE_DISPLAY_AREAS = True +# number of day before an event to display +# if equal to 0: disable event management +# if you change this value from 0 to a value in a production environnement +# don't forget to run the upgrade.py script to create appropriate fields in +# the database +CHIMERE_DAYS_BEFORE_EVENT = 30 +# allow feeds +CHIMERE_FEEDS = True + +CHIMERE_ICON_WIDTH = 21 +CHIMERE_ICON_HEIGHT = 25 +CHIMERE_ICON_OFFSET_X = -10 +CHIMERE_ICON_OFFSET_Y = -25 + +# display picture inside the description by default or inside a galery? +CHIMERE_MINIATURE_BY_DEFAULT = False + +# JS definition of the default map (for admin and when no map are defined in +# the application) +# cf. OpenLayers documentation for more details +CHIMERE_DEFAULT_MAP_LAYER = "new OpenLayers.Layer.OSM.Mapnik('Mapnik')" # OSM mapnik map + +CHIMERE_XAPI_URL = 'http://open.mapquestapi.com/xapi/api/0.6/' +CHIMERE_OSM_API_URL = 'api06.dev.openstreetmap.org' # test URL +CHIMERE_OSM_USER = 'test' +CHIMERE_OSM_PASSWORD = 'test' + +# encoding for shapefile import +CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' + +# as the web server need to be reloaded when property models are changed +# it could be a good idea to hide it to an admin who could'nt do that +CHIMERE_HIDE_PROPERTYMODEL = False + +# enable routing in Chimère +CHIMERE_ENABLE_ROUTING = False + +CHIMERE_ROUTING_TRANSPORT = (('foot', _(u"Foot")), + ('bicycle', _(u"Bicycle")), + ('motorcar', _(u"Motorcar")), + ) + +CHIMERE_ROUTING_SPEEDS = {'foot':((3, _(u"You are walking slowly")), + (6, _(u"You are walking pretty quickly")),), + 'bicycle':((16, _(u"You are riding pretty slowly")), + (22, _(u"You are riding pretty quickly")),) + } + +# available routing engine: 'routino' +CHIMERE_ROUTING_ENGINE = { + 'ENGINE': 'routino', + 'PATH': '/usr/local/src/web/bin/router', + 'DB_PATH': '/var/local/routino/', +} + +CHIMERE_ROUTING_FAIL_MESSAGE = u"""<h3 class='warn'>Attention</h3> +<p>Le moteur de routage a échoué dans sa recherche de trajet. Les points de +départ ou d'arrivée sont peut-être trop loin d'une voie existante ou le trajet +est trop dangereux.</p>""" + +NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search' + +# thumbnail +CHIMERE_THUMBS_SCALE_HEIGHT=250 +CHIMERE_THUMBS_SCALE_WIDTH=None + +CHIMERE_CSV_ENCODING = 'ISO-8859-1' + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'NAME': 'ratatouille', + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'HOST': 'localhost', + 'PORT': '5432', + 'USER': 'ratatouille', + 'PASSWORD': 'wiki', + }, +} + +# Local time zone for this installation. Choices can be found here: +# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE +# although not all variations may be possible on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Paris' + +# Language code for this installation. All choices can be found here: +# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://blogs.law.harvard.edu/tech/stories/storyReader$15 +LANGUAGE_CODE = 'fr-fr' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True +USE_L10N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = ROOT_PATH + 'media/' + +# URL that handles the media served from MEDIA_ROOT. +# Example: "http://media.lawrence.com" +MEDIA_URL = '/media/' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.doc.XViewMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware' +) + +ROOT_URLCONF = 'chimere_example_project.urls' + +TEMPLATE_DIRS = [ + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + ROOT_PATH + 'templates', +] + +TEMPLATE_CONTEXT_PROCESSORS = ( + "django.contrib.auth.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media", + "django.core.context_processors.static", + "django.contrib.messages.context_processors.messages", + "django.core.context_processors.request", +) + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.admin', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.gis', + 'django.contrib.staticfiles', +] + +# celery +try: + import djcelery + import kombu + djcelery.setup_loader() + BROKER_URL = 'django://' + INSTALLED_APPS += ['kombu.transport.django', + 'djcelery'] +except ImportError: + # some import and export will not be available + pass + +INSTALLED_APPS += [ + 'south', + 'chimere', +] + +LOG_PATH = '/var/log/django/' + +try: + from local_settings import * +except ImportError, e: + print 'Unable to load local_settings.py:', e + +if 'LOGGING' not in globals(): + global LOGGING + LOGGING = {'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + # Include the default Django email handler for errors + # This is what you'd get without configuring logging at all. + 'mail_admins': { + 'class': 'django.utils.log.AdminEmailHandler', + 'level': 'ERROR', + # But the emails are plain text by default - HTML is nicer + 'include_html': True, + }, + # Log to a text file that can be rotated by logrotate + 'logfile': { + 'class': 'logging.handlers.WatchedFileHandler', + 'filename': LOG_PATH + 'chimere.log' + }, + }, + 'loggers': { + # Again, default Django configuration to email unhandled exceptions + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + # Might as well log any errors anywhere else in Django + 'django': { + 'handlers': ['logfile'], + 'level': 'ERROR', + 'propagate': False, + }, + # Your own app - this assumes all your logger names start with "myapp." + 'chimere': { + 'handlers': ['logfile'], + 'level': 'WARNING', # Or maybe INFO or DEBUG + 'propogate': False + }, + }, + } + + +if 'CHIMERE_SHARE_NETWORKS' not in globals(): + # after the locals to get the right STATIC_URL + + # share with + global CHIMERE_SHARE_NETWORKS + CHIMERE_SHARE_NETWORKS = ( + ("Email", 'mailto:?subject=%(text)s&body=%(url)s', + STATIC_URL + 'chimere/img/email.png'), + ("Facebook", 'http://www.facebook.com/sharer.php?t=%(text)s&u=%(url)s', + STATIC_URL + 'chimere/img/facebook.png'), + ("Twitter", 'http://twitter.com/home?status=%(text)s %(url)s', + STATIC_URL + 'chimere/img/twitter.png'), + ("Identi.ca", 'http://identi.ca/index.php?action=newnotice&status_textarea=%(text)s %(url)s', + STATIC_URL + 'chimere/img/identica.png'), + ) + +if 'OSM_JS_URLS' not in globals(): + global OSM_JS_URLS + OSM_JS_URLS = [STATIC_URL + "openlayers/OpenLayers.js", + STATIC_URL + "openlayers/SimplePanZoom.js", + "http://www.openstreetmap.org/openlayers/OpenStreetMap.js"] + diff --git a/chimere/static/chimere/css/admin.css b/chimere/static/chimere/css/admin.css new file mode 100644 index 0000000..931d139 --- /dev/null +++ b/chimere/static/chimere/css/admin.css @@ -0,0 +1,6 @@ +.vTextField{ + width:150px; +} +.vLargeTextField{ + width:200px; +} diff --git a/chimere/static/chimere/css/print.css b/chimere/static/chimere/css/print.css new file mode 100644 index 0000000..8dda0b8 --- /dev/null +++ b/chimere/static/chimere/css/print.css @@ -0,0 +1,40 @@ +#topbar, .no-titlebar-simple.ui-dialog, +#zoombar, #zoomin, #zoomout, #slidebar, +#pandown, #panup, #panright, #panleft, +div#footer p.map-footer{ + display:none; +} + +#main-map{ + z-index:10; + top:0; + bottom:0; + height:605pt; + max-height:605pt; + width:1200pt; + right:50%; + border:none; +} + +#panel #chimere_itinerary_panel{ + width:870pt; + bottom:auto; + left:auto; + right:auto; + top:605pt; + position:absolute; + z-index:1000; +} + +#sidebar div#panel{ + width:900pt; + border:none; + overflow:visible; +} + +#chimere_start_label, +#chimere_end_label{ + width:auto; + overflow:auto; +} + diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 9d26b67..ea7d4c0 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -15,7 +15,9 @@ a, a:link, a:visited, legend, h2, h3, th, .action li, .action li a, .action li li a, #no-js-message, -#footer a, #footer a:link, #footer a:visited, .ui-widget-header{ +#footer a, #footer a:link, #footer a:visited, .ui-widget-header, +#layer_selection h4, +#chimere_itinerary td.l{ color:#fff; } @@ -25,11 +27,23 @@ h2, h3, th, .action li, .action li a, color:#333; } +.nominatim-widget, .disabled{ + color:#aaa; +} + +#chimere_total_label td.l{ + color:#000; +} + /* background-color definition */ body, h2, h3, th, .ui-widget-header, -.action li.selected, #no-js-message{ +#layer_selection h4, +.action li.selected, #no-js-message, +#content .olControlLayerSwitcher .layersDiv, +#content .olControlLayerSwitcher span, +#chimere_itinerary td.l{ background-color:#449506; } @@ -38,10 +52,12 @@ body, h2, h3, th, } fieldset, .action li, #content, -#map-footer, #panel, #areas, +#layer_selection #layer_list, +#map-footer, #panel, #chimere_itinerary_panel, #areas, #welcome, #detail, .detail_footer a, #content .olControlLayerSwitcher .layersDiv, #content .olControlLayerSwitcher span, +#chimere_total_label td.l, #main-map, .window{ background-color:#FFF; } @@ -58,12 +74,14 @@ div.warning, .errorlist{ border:1px solid #54c200; } +#layer_selection h4, +#layer_selection #layer_list, #areas, #detail, #main-map, div.warning, #content, .action li.selected, #content .olControlLayerSwitcher .layersDiv, -#panel, #map-footer, +#panel, #map-footer, #chimere_itinerary_panel, #utils-div{ border:1px solid #327e04; } @@ -92,7 +110,7 @@ h2, #action li, .detail_footer{ fieldset, #content, #panel, #areas, #welcome, #detail, -#category_detail, div.warning{ +#category_description, div.warning{ -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; @@ -143,7 +161,6 @@ h3{ h4, caption{ font-weight:normal; - font-style:italic; margin:0; text-align:left; } @@ -164,6 +181,10 @@ fieldset{ margin-top:8px; } +.hidden{ + display:none; +} + .ui-dialog-buttonset{ text-align:center; } @@ -182,7 +203,7 @@ fieldset{ } #topbar{ - z-index:0; + z-index:10; } ul.action{ @@ -243,8 +264,14 @@ ul#action-2 { width:auto; } +#utils-div a{ + display:block; + width:100%; +} + #areas-div, -#areas-div label{ +#areas-div label, +#utils-div a{ padding:0.3em; } @@ -314,6 +341,7 @@ ul.share{ list-style-type:none; margin:0; padding:0; + display:inline; } ul.share li{ @@ -332,6 +360,10 @@ ul.share li{ height:22px; } +.share .share-icon img{ + width:74px; +} + .detail_footer{ text-align:center; position:absolute; @@ -356,8 +388,6 @@ ul.share li{ #main-map{ position:absolute; - margin:0px; - padding:0px; height:93%; margin:0; padding:0; @@ -388,6 +418,45 @@ ul.share li{ z-index:0; } +#layer_selection{ + position:absolute; + z-index:100; + top:280px; + left:24px; +} + +#layer_selection h4, +#layer_selection #layer_list li{ + padding:2px 5px; +} + +#layer_selection h4{ + font-weight:normal; + border-width:1px; + border-style:solid; + width:140px; + text-align:center; +} + +#layer_selection h4:hover{ + cursor:pointer; +} + +#layer_selection ul{ + display:block; +} + +#layer_selection ul#layer_list{ + width:150px; + display:none; + list-style:none; + margin:0; + padding:0; + border-width:1px; + border-style:solid; + border-top:none; +} + .news h3{ padding:0px; margin:0; @@ -410,12 +479,110 @@ ul.share li{ top:50px; right:18px; width:300px; - bottom:44px; + max-height:300px; overflow:auto; padding:0.5em; padding-top:0; } +#chimere_itinerary_panel, +#chimere_itinerary{ + display:none; +} + +#chimere_itinerary_panel label{ + color:#000; +} + +#chimere_itinerary_panel p +{ + margin:0.5em; +} + +#total_label_div{ + margin:5px 0; +} + +.itinerary_label{ + font-size:0.9em; + padding-top:0.5em; + font-style:italic; +} + +.itinerary_label .label{ + font-style:normal; + font-weight:bold; + padding:3px 8px; +} + + +#chimere_itinerary_content{ + overflow:auto; + height:190px; + margin-top:10px; +} + +#chimere_itinerary_content span.l{ + padding:5px; + width:60px; +} + +#chimere_itinerary_content span.j{ + font-style:italic; +} + +#chimere_itinerary_content .number{ + font-weight:bold; +} + +#chimere_itinerary_content span.t, +#chimere_itinerary_content span.b +{ + text-transform: lowercase; +} + +#chimere_map_menu{ + z-index:4; + display:none; + position:absolute; + padding:0.5em; + background-color:#fff; + border:1px solid #bbb; + -webkit-border-radius: 0 8px 8px 8px; + -moz-border-radius: 0 8px 8px 8px; + border-radius: 0 8px 8px 8px; +} + +#map_menu_clear{ + display:none; +} + +#map_menu_zoomin{ + border-top:1px solid #999; +} + +#chimere_map_menu ul, #chimere_map_menu li{ + padding:0.2em; + margin:0; + list-style:none; +} + +#chimere_map_menu li:hover{ + cursor:pointer; + background-color:#ccc; +} + +.nominatim-label{ + display:block; + font-size:0.9em; + font-weight:bold; + height:2.8em; +} + +.nominatim-widget{ + font-style:italic; +} + .simple #panel{ top:5px; bottom:auto; @@ -494,6 +661,11 @@ ul.subcategories label img{ height:20px; } +li.main_category > span:hover, +li.main_category label:hover{ + cursor:pointer; +} + #categories li#display_submited{ font-variant:normal; } @@ -546,11 +718,10 @@ p.warning{ } -#welcome_button, -#simple_button, +a#welcome_button, +a#routing_button, #permalink{ display: block; - text-align:center; margin:0.3em; padding:0.2em; width:100%; @@ -601,6 +772,40 @@ table.inline-table td input[type=file]{ margin-right: auto; } +.alert-box .ui-dialog-titlebar { + display:none; +} + +ul#multimedia_list_content{ + padding:0; + margin:0; + list-style-type:none; +} + +ul#multimedia_list_content li{ + padding:0.5em 5px 0.5em 35px; + margin:0; + display:block; + list-style-type:none; + border-bottom:1px solid; +} + +ul#multimedia_list_content li img{ + display:block; + float:right; +} + +ul#multimedia_list_content li.picture{ + background-image:url("../img/img_logo.png"); + background-position:4px center; + background-repeat:no-repeat; +} + +ul#multimedia_list_content li.multimedia{ + background-image:url("../img/film_logo.png"); + background-position:6px center; + background-repeat:no-repeat; +} #waiting{ /* Fixed position to provide the vertical offset */ position:fixed; @@ -746,7 +951,7 @@ p.legend{ } .media-img{ - max-height:400px; + max-height:200px; } .media-video, @@ -799,6 +1004,26 @@ div.pp_default .pp_expand{ SimplePanZoom */ +#main_map.olMap{ + z-index:0; +} + +#marker_hover{ + display:none; + position:absolute; + z-index:5; + background-image: url('../img/bottom-arrow.png'); + background-repeat: no-repeat; + background-position: center bottom; +} + +#marker_hover_content{ + margin-bottom:6px; + background-color:#fff; + border:1px solid #000; + padding:0.1em 0.5em; +} + .olControlSimplePanZoom { top: 10px; right: 10px; diff --git a/chimere/static/chimere/img/bottom-arrow.png b/chimere/static/chimere/img/bottom-arrow.png Binary files differnew file mode 100644 index 0000000..7393ffe --- /dev/null +++ b/chimere/static/chimere/img/bottom-arrow.png diff --git a/chimere/static/chimere/img/close.png b/chimere/static/chimere/img/close.png Binary files differnew file mode 100644 index 0000000..f9e8d04 --- /dev/null +++ b/chimere/static/chimere/img/close.png diff --git a/chimere/static/chimere/img/empty.png b/chimere/static/chimere/img/empty.png Binary files differnew file mode 100644 index 0000000..1ad1e19 --- /dev/null +++ b/chimere/static/chimere/img/empty.png diff --git a/chimere/static/chimere/img/feed.png b/chimere/static/chimere/img/feed.png Binary files differnew file mode 100644 index 0000000..19d2246 --- /dev/null +++ b/chimere/static/chimere/img/feed.png diff --git a/chimere/static/chimere/img/film_logo.png b/chimere/static/chimere/img/film_logo.png Binary files differnew file mode 100644 index 0000000..1ccdc2e --- /dev/null +++ b/chimere/static/chimere/img/film_logo.png diff --git a/chimere/static/chimere/img/flag-finish.png b/chimere/static/chimere/img/flag-finish.png Binary files differnew file mode 100644 index 0000000..04bfa1d --- /dev/null +++ b/chimere/static/chimere/img/flag-finish.png diff --git a/chimere/static/chimere/img/flag-start.png b/chimere/static/chimere/img/flag-start.png Binary files differnew file mode 100644 index 0000000..c93f2a3 --- /dev/null +++ b/chimere/static/chimere/img/flag-start.png diff --git a/chimere/static/chimere/img/flag-step.png b/chimere/static/chimere/img/flag-step.png Binary files differnew file mode 100644 index 0000000..5556c94 --- /dev/null +++ b/chimere/static/chimere/img/flag-step.png diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 0e732fc..d6d2773 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -1,5 +1,5 @@ -* Upload image credit +* Upload image credit (upload.png) * Farm-Fresh layer gps.png in Farm-Fresh Web Icons Author: FatCow Web Hosting @@ -16,17 +16,26 @@ Author: The Tango! Desktop Project Licence: Public domain Url: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg -* Drawing image credit +* Drawing image credit (drawing.png) * Icons from the Tango! project set. Author: The Tango! Desktop Project Licence: Public domain Url: http://commons.wikimedia.org/wiki/File:Edit-find-replace.svg -Url 2: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg + http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg + https://commons.wikimedia.org/wiki/File:Document-print.svg -* Quaver image credit +* Quaver image credit (8thNote.png) * An 8th-note. Author: Sbrools Licence: Public domain Url: https://commons.wikimedia.org/wiki/File:8thNote.svg + +* Flags image credit (flag-start.png, flag-step.png, flag-finish.png) + +Author: FatCow Web Hosting +Licence: Creative Commons Attribution 3.0 United States license +Url: https://upload.wikimedia.org/wikipedia/commons/c/cb/Farm-Fresh_flag_1.png + https://upload.wikimedia.org/wikipedia/commons/8/81/Farm-Fresh_flag_blue.png + https://upload.wikimedia.org/wikipedia/commons/6/64/Farm-Fresh_flag_finish.png diff --git a/chimere/static/chimere/img/img_logo.png b/chimere/static/chimere/img/img_logo.png Binary files differnew file mode 100644 index 0000000..b487506 --- /dev/null +++ b/chimere/static/chimere/img/img_logo.png diff --git a/chimere/static/chimere/img/marker-cluster.png b/chimere/static/chimere/img/marker-cluster.png Binary files differnew file mode 100644 index 0000000..73b4146 --- /dev/null +++ b/chimere/static/chimere/img/marker-cluster.png diff --git a/chimere/static/chimere/img/printer.png b/chimere/static/chimere/img/printer.png Binary files differnew file mode 100644 index 0000000..5a5dbaf --- /dev/null +++ b/chimere/static/chimere/img/printer.png diff --git a/chimere/static/chimere/img/share-icon.png b/chimere/static/chimere/img/share-icon.png Binary files differnew file mode 100644 index 0000000..f21b76e --- /dev/null +++ b/chimere/static/chimere/img/share-icon.png diff --git a/chimere/static/chimere/img/share-icon.xcf b/chimere/static/chimere/img/share-icon.xcf Binary files differnew file mode 100644 index 0000000..d149768 --- /dev/null +++ b/chimere/static/chimere/img/share-icon.xcf diff --git a/chimere/static/chimere/js/base.js b/chimere/static/chimere/js/base.js index e76fe76..fe8d954 100644 --- a/chimere/static/chimere/js/base.js +++ b/chimere/static/chimere/js/base.js @@ -1,5 +1,5 @@ /* base function shared by some pages */ -/* Copyright (C) 2009-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +/* Copyright (C) 2009-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -107,3 +107,37 @@ function zoomToCurrentExtent(map){ map.zoomToExtent(extent, true); return true; } + +/* interface */ +function share_link_update(){ + $('.share_link').click(function(){ + if (this.share_initialized){ + return false; + } + this.share_initialized = true; + var href = $(this).attr('href'); + var url = get_share_url; + var classes = $(this).attr('class').split(' '); + prefix = 'share_id_'; + var share_id; + for (idx=0;idx<classes.length;idx++){ + if(classes[idx].substring(0, prefix.length) == prefix){ + var share_id = classes[idx].substring(prefix.length); + share_id = share_id.split('_')[0]; + } + } + var params = $('#permalink a').attr('href').split('/'); + url += share_id + params[params.length-1]; + $.ajax({url: url, + dataType: "html", + success: function (url) { + window.location.href = url; + return true; + }, + error: function(){ + return false; + } + }); + return false; + }); +} diff --git a/chimere/static/chimere/js/clustering.js b/chimere/static/chimere/js/clustering.js new file mode 100644 index 0000000..b3a142c --- /dev/null +++ b/chimere/static/chimere/js/clustering.js @@ -0,0 +1,278 @@ +/* + Add a recluster to Cluster class. + probably part of OpenLayers 2.13 +*/ + + +OpenLayers.Strategy.Cluster = OpenLayers.Class(OpenLayers.Strategy, { + + /** + * APIProperty: distance + * {Integer} Pixel distance between features that should be considered a + * single cluster. Default is 20 pixels. + */ + distance: 20, + + /** + * APIProperty: threshold + * {Integer} Optional threshold below which original features will be + * added to the layer instead of clusters. For example, a threshold + * of 3 would mean that any time there are 2 or fewer features in + * a cluster, those features will be added directly to the layer instead + * of a cluster representing those features. Default is null (which is + * equivalent to 1 - meaning that clusters may contain just one feature). + */ + threshold: null, + + /** + * Property: features + * {Array(<OpenLayers.Feature.Vector>)} Cached features. + */ + features: null, + + /** + * Property: clusters + * {Array(<OpenLayers.Feature.Vector>)} Calculated clusters. + */ + clusters: null, + + /** + * Property: clustering + * {Boolean} The strategy is currently clustering features. + */ + clustering: false, + + /** + * Property: resolution + * {Float} The resolution (map units per pixel) of the current cluster set. + */ + resolution: null, + + /** + * Constructor: OpenLayers.Strategy.Cluster + * Create a new clustering strategy. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + */ + + /** + * APIMethod: activate + * Activate the strategy. Register any listeners, do appropriate setup. + * + * Returns: + * {Boolean} The strategy was successfully activated. + */ + activate: function() { + var activated = OpenLayers.Strategy.prototype.activate.call(this); + if(activated) { + this.layer.events.on({ + "beforefeaturesadded": this.cacheFeatures, + "moveend": this.cluster, + scope: this + }); + } + return activated; + }, + + /** + * APIMethod: deactivate + * Deactivate the strategy. Unregister any listeners, do appropriate + * tear-down. + * + * Returns: + * {Boolean} The strategy was successfully deactivated. + */ + deactivate: function() { + var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this); + if(deactivated) { + this.clearCache(); + this.layer.events.un({ + "beforefeaturesadded": this.cacheFeatures, + "moveend": this.cluster, + scope: this + }); + } + return deactivated; + }, + + /** + * Method: cacheFeatures + * Cache features before they are added to the layer. + * + * Parameters: + * event - {Object} The event that this was listening for. This will come + * with a batch of features to be clustered. + * + * Returns: + * {Boolean} False to stop features from being added to the layer. + */ + cacheFeatures: function(event) { + var propagate = true; + if(!this.clustering) { + this.clearCache(); + this.features = event.features; + this.cluster(); + propagate = false; + } + return propagate; + }, + + /** + * Method: clearCache + * Clear out the cached features. + */ + clearCache: function() { + this.features = null; + }, + + /** + * Method: cluster + * Cluster features based on some threshold distance. + * + * Parameters: + * event - {Object} The event received when cluster is called as a + * result of a moveend event. + */ + cluster: function(event) { + if((!event || event.zoomChanged || (event && event.recluster)) && this.features) { + var resolution = this.layer.map.getResolution(); + if(resolution != this.resolution || !this.clustersExist() || (event && event.recluster)) { + this.resolution = resolution; + var clusters = []; + var feature, clustered, cluster; + for(var i=0; i<this.features.length; ++i) { + feature = this.features[i]; + if(feature.geometry) { + clustered = false; + for(var j=clusters.length-1; j>=0; --j) { + cluster = clusters[j]; + if(this.shouldCluster(cluster, feature)) { + this.addToCluster(cluster, feature); + clustered = true; + break; + } + } + if(!clustered) { + clusters.push(this.createCluster(this.features[i])); + } + } + } + this.layer.removeAllFeatures(); + if(clusters.length > 0) { + if(this.threshold > 1) { + var clone = clusters.slice(); + clusters = []; + var candidate; + for(var i=0, len=clone.length; i<len; ++i) { + candidate = clone[i]; + if(candidate.attributes.count < this.threshold) { + Array.prototype.push.apply(clusters, candidate.cluster); + } else { + clusters.push(candidate); + } + } + } + this.clustering = true; + // A legitimate feature addition could occur during this + // addFeatures call. For clustering to behave well, features + // should be removed from a layer before requesting a new batch. + this.layer.addFeatures(clusters); + this.clustering = false; + } + this.clusters = clusters; + } + } + }, + + /** + * Method: recluster + * User-callable function to recluster features + * Useful for instances where a clustering attribute (distance, threshold, ...) + * has changed + */ + recluster: function(){ + var event={"recluster":true}; + this.cluster(event); + }, + + /** + * Method: clustersExist + * Determine whether calculated clusters are already on the layer. + * + * Returns: + * {Boolean} The calculated clusters are already on the layer. + */ + clustersExist: function() { + var exist = false; + if(this.clusters && this.clusters.length > 0 && + this.clusters.length == this.layer.features.length) { + exist = true; + for(var i=0; i<this.clusters.length; ++i) { + if(this.clusters[i] != this.layer.features[i]) { + exist = false; + break; + } + } + } + return exist; + }, + + /** + * Method: shouldCluster + * Determine whether to include a feature in a given cluster. + * + * Parameters: + * cluster - {<OpenLayers.Feature.Vector>} A cluster. + * feature - {<OpenLayers.Feature.Vector>} A feature. + * + * Returns: + * {Boolean} The feature should be included in the cluster. + */ + shouldCluster: function(cluster, feature) { + var cc = cluster.geometry.getBounds().getCenterLonLat(); + var fc = feature.geometry.getBounds().getCenterLonLat(); + var distance = ( + Math.sqrt( + Math.pow((cc.lon - fc.lon), 2) + Math.pow((cc.lat - fc.lat), 2) + ) / this.resolution + ); + return (distance <= this.distance); + }, + + /** + * Method: addToCluster + * Add a feature to a cluster. + * + * Parameters: + * cluster - {<OpenLayers.Feature.Vector>} A cluster. + * feature - {<OpenLayers.Feature.Vector>} A feature. + */ + addToCluster: function(cluster, feature) { + cluster.cluster.push(feature); + cluster.attributes.count += 1; + }, + + /** + * Method: createCluster + * Given a feature, create a cluster. + * + * Parameters: + * feature - {<OpenLayers.Feature.Vector>} + * + * Returns: + * {<OpenLayers.Feature.Vector>} A cluster. + */ + createCluster: function(feature) { + var center = feature.geometry.getBounds().getCenterLonLat(); + var cluster = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(center.lon, center.lat), + {count: 1} + ); + cluster.cluster = [feature]; + return cluster; + }, + + CLASS_NAME: "OpenLayers.Strategy.Cluster" +}); diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 6675dcd..2e2d238 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -68,6 +68,11 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { lat: null, lon: null, simple: false, + routing_start_lat: null, + routing_start_lon: null, + routing_end_lat: null, + routing_end_lon: null, + routing_steps_lonlat: null, // Provide this function to make a custom click event on the marker on_marker_click: null, // Provide this function to override the feature detail display @@ -75,24 +80,44 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // Provide this function for overriding the getSubcategories default get_subcategories_fx: null, hide_popup_fx: null, + // if leave to false every click on the map hide the pop-up + explicit_popup_hide: false, controls:[new OpenLayers.Control.Navigation(), - new OpenLayers.Control.SimplePanZoom(), + new OpenLayers.Control.PanPanel(), + new OpenLayers.Control.ZoomPanel(), new OpenLayers.Control.ScaleLine()], + popupClass: OpenLayers.Popup.FramedCloud, + popupContentFull: false, // if true the detail is inside the popup + category_accordion: true, // category opening behave like an accordion maxResolution: 156543.0399, units: 'm', projection: new OpenLayers.Projection('EPSG:4326'), - theme:null, + theme: null, + enable_clustering: false, + routing: false, // enable routing management + routing_panel_open: function(){ + $('#chimere_itinerary_panel').dialog('open'); + }, current_feature: null, // To store the active POI current_control: null, // To store the current control current_popup: null, // To store the current POI popup displayed current_category: null, // To store the current category clicked in list + current_route_feature: null, // To store the current route find by routing + itinerary_step_number:0, // current step number icon_offset: new OpenLayers.Pixel(0, 0), edition: false, // edition mode edition_type_is_route: false, // route or POI edition default_icon: new OpenLayers.Icon( 'http://www.openlayers.org/dev/img/marker-green.png', new OpenLayers.Size(21, 25), - new OpenLayers.Pixel(-(21/2), -25)) + new OpenLayers.Pixel(-(21/2), -25)), + cluster_icon: null, + marker_hover_id:'marker_hover', + marker_hover_content_id:'marker_hover_content', + marker_hover_offset: null, + icon_start: null, + icon_step: null, + icon_end: null }; var settings = {}; /* @@ -104,6 +129,31 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { */ init: function ( options ) { /* Manage parameters */ + // not staticaly in default because of STATIC_URL init + if (defaults.cluster_icon == null && typeof STATIC_URL != 'undefined'){ + defaults.cluster_icon = new OpenLayers.Icon( + STATIC_URL+'chimere/img/marker-cluster.png', + new OpenLayers.Size(36, 39), + new OpenLayers.Pixel(-(36/2), -(39/2))); + } + if (defaults.icon_start == null && typeof STATIC_URL != 'undefined'){ + defaults.icon_start = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-start.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + } + if (defaults.icon_step == null && typeof STATIC_URL != 'undefined'){ + defaults.icon_step = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-step.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + } + if (defaults.icon_end == null && typeof STATIC_URL != 'undefined'){ + defaults.icon_end = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-finish.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + } settings = $.extend({}, defaults); if ( options ) $.extend(settings, options); var map_element = $(this).get(0); @@ -120,6 +170,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { map_options['restrictedExtent'] = settings.restricted_extent; } + settings.current_position = null; + /* Create map object */ settings.map = map = new OpenLayers.Map(map_element, map_options); @@ -145,8 +197,29 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // Make specific params params.checked_categories = settings.checked_categories; params.display_submited = settings.display_submited; - if(settings.current_feature){ + if(settings.current_feature) params.current_feature = settings.current_feature.pk; + if (settings.routing_start){ + lonlat = settings.routing_start.lonlat.clone().transform( + EPSG_PROJECTION, EPSG_DISPLAY_PROJECTION); + params.routing_start_lon = lonlat.lon; + params.routing_start_lat = lonlat.lat; + } + if (settings.routing_end){ + lonlat = settings.routing_end.lonlat.clone().transform( + EPSG_PROJECTION, EPSG_DISPLAY_PROJECTION); + params.routing_end_lon = lonlat.lon; + params.routing_end_lat = lonlat.lat; + } + if (settings.routing_steps){ + var steps = []; + for (var i = 0; i < settings.routing_steps.length; i++){ + lonlat = settings.routing_steps[i].lonlat.clone( + ).transform(EPSG_PROJECTION, + EPSG_DISPLAY_PROJECTION); + steps.push([lonlat.lon, lonlat.lat]); + } + params.routing_steps = steps; } return params; } @@ -171,6 +244,26 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } settings.map.setBaseLayer( settings.map_layers[settings.selected_map_layer]); + + /* manage the context menu */ + $('#map_menu_zoomin').bind("click", methods.zoomIn); + $('#map_menu_zoomout').bind("click", methods.zoomOut); + $('#map_menu_center').bind("click", methods.mapCenter); + /* manage the routing */ + if (settings.routing){ + settings.routing_start = null; + settings.routing_steps = new Array(); + settings.routing_end = null; + $('#map_menu_from').bind("click", methods.routingFrom); + $('#map_menu_step').bind("click", methods.routingAddStep); + $('#map_menu_to').bind("click", methods.routingTo); + $('#map_menu_clear').bind("click", methods.routingClear); + settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); + settings.map.addLayer(settings.layerRoute); + settings.layerRouteMarker = new OpenLayers.Layer.Markers( + 'Route markers'); + settings.map.addLayer(settings.layerRouteMarker); + } /* Vectors layer */ settings.layerVectors = new OpenLayers.Layer.Vector("Vector Layer"); settings.map.addLayer(settings.layerVectors); @@ -181,10 +274,94 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.map.addControl(new OpenLayers.Control.ModifyFeature( settings.layerVectors, {clickout:false, toggle:false})); } + + if (settings.enable_clustering){ + var style = new OpenLayers.Style({ + graphicTitle: "${name}", + externalGraphic: "${icon}", + graphicWidth: "${width}", + graphicHeight: "${height}", + graphicXOffset: "${offsetx}", + graphicYOffset: "${offsety}", + graphicOpacity: 1, + label: "${label}", + labelYOffset: "2", + fontSize:'1.3em' + }, { + context: { + name: function(feature) { + if(feature.cluster) { + feature.attributes.width = settings.cluster_icon.size.w; + feature.attributes.height = settings.cluster_icon.size.h; + feature.attributes.offsetx = settings.cluster_icon.offset.x; + feature.attributes.offsety = settings.cluster_icon.offset.y; + } else{ + var marker = feature.attributes.marker + feature.attributes.width = marker.icon.size.w; + feature.attributes.height = marker.icon.size.h; + feature.attributes.offsetx = settings.icon_offset.x; + feature.attributes.offsety = settings.icon_offset.y; + } + return feature.attributes.name; + }, + label: function(feature) { + // clustered features count or blank if feature is not a cluster + return feature.cluster ? feature.cluster.length : ""; + }, + icon: function(feature) { + if (feature.cluster){ + return settings.cluster_icon.url; + } else { + return STATIC_URL + 'chimere/img/empty.png'; + } + }, + width: function(feature) { return feature.attributes.width; }, + height: function(feature) { return feature.attributes.height; }, + offsetx: function(feature) { return feature.attributes.offsetx; }, + offsety: function(feature) { return feature.attributes.offsety; } + }}); + + + /* Cluster layer */ + settings.clustering = new OpenLayers.Strategy.Cluster({ + distance: 10, + threshold: 2}); + settings.layerCluster = new OpenLayers.Layer.Vector("Cluster layer", + {styleMap: new OpenLayers.StyleMap({'default': style}), + strategies: [settings.clustering]}); + settings.map.addLayer(settings.layerCluster); + + var highlightCtrl = new OpenLayers.Control.SelectFeature( + settings.layerCluster, { + hover: true, + highlightOnly: true, + eventListeners: { + featurehighlighted: function(e) { + if(e.feature.attributes.marker) + e.feature.attributes.marker.events.triggerEvent('mouseover'); + }, + featureunhighlighted: function(e) { + if(e.feature.attributes.marker) + e.feature.attributes.marker.events.triggerEvent('mouseout'); + } + } + }); + + var selectCtrl = new OpenLayers.Control.SelectFeature( + settings.layerCluster,{ + onSelect: methods.zoomOnCluster + }); + + settings.map.addControl(highlightCtrl); + settings.map.addControl(selectCtrl); + + highlightCtrl.activate(); + selectCtrl.activate(); + } + /* Markers layer */ settings.layerMarkers = new OpenLayers.Layer.Markers('POIs'); settings.map.addLayer(settings.layerMarkers); - settings.layerMarkers.setOpacity(0.8); if (settings.dynamic_categories){ settings.map.events.register('moveend', settings.map, @@ -209,15 +386,16 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } if (!settings.edition){ + if (settings.enable_clustering){ + settings.map.events.register('zoomend', null, + methods.cleanCluster); + } methods.loadCategories(); methods.loadGeoObjects(); - // Hide popUp when clicking on map - settings.map.events.register('click', settings.map, - methods.hidePopup); + methods.activateContextMenu() } else { if (!settings.edition_type_is_route){ - map.events.register('click', settings.map, - methods.setMarker); + methods.activateMarkerEdit(); } else { settings.layerVectors.events.register('featuremodified', settings.layerVectors, helpers.updateRouteForm); @@ -225,9 +403,139 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.layerVectors, helpers.featureRouteCreated); } } + if (settings.routing_start_lon && settings.routing_start_lat){ + settings.current_position = new OpenLayers.LonLat( + settings.routing_start_lon, settings.routing_start_lat + ).transform(EPSG_DISPLAY_PROJECTION, EPSG_PROJECTION); + methods.routingFrom(); + } + if (settings.routing_end_lon && settings.routing_end_lat){ + settings.current_position = new OpenLayers.LonLat( + settings.routing_end_lon, settings.routing_end_lat + ).transform(EPSG_DISPLAY_PROJECTION, EPSG_PROJECTION); + methods.routingTo(); + } + if (settings.routing_steps_lonlat){ + for (var i = 0; i < settings.routing_steps_lonlat.length/2; i++) { + lon = settings.routing_steps_lonlat[i*2]; + lat = settings.routing_steps_lonlat[i*2+1]; + settings.current_position = new OpenLayers.LonLat(lon, lat + ).transform(EPSG_DISPLAY_PROJECTION, EPSG_PROJECTION); + methods.routingAddStep(); + } + } + methods.preload_images(); }, // end of init + /* Preload icons */ + preload_images: function(){ + if (typeof extra_url == 'undefined') return; + var uri = extra_url + "getAllCategories/"; + $.ajax({url: uri, + dataType: "json", + success: function (data) { + if (!data.categories){return} + for(var idx=0; idx<data.categories.length; idx++){ + new Image().src = data.categories[idx].icon.url; + if(data.categories[idx].icon_hover){ + new Image().src = + data.categories[idx].icon_hover.url; + } + } + }, + error: function (data) { + // fail silently + } + }); + }, + + activateContextMenu: function(){ + settings.edition_type_is_route = false; + settings.map.events.unregister('click', settings.map, + methods.setMarker); + settings.map.events.register('click', settings.map, + methods.displayMapMenu); + }, + + activateRouteEdit: function(){ + settings.edition_type_is_route = true; + settings.map.events.unregister('click', settings.map, + methods.setMarker); + settings.map.events.register('click', settings.map, + methods.displayMapMenu); + }, + + activateMarkerEdit: function(){ + settings.edition_type_is_route = false; + if ($('#chimere_map_menu').length){ + $('#chimere_map_menu').hide(); + } + if (settings.current_popup != null) { + settings.current_popup.hide(); + } + settings.map.events.unregister('click', settings.map, + methods.displayMapMenu); + settings.map.events.register('click', settings.map, + methods.setMarker); + }, + // change map_layer + changeMapLayer: function(map_idx){ + settings.map.setBaseLayer(settings.map_layers[map_idx]); + }, + + // init the context menu + zoomIn: function(){ + methods.mapCenter(); + settings.map.zoomIn(); + }, + + // zoom out from the map menu + zoomOut: function(){ + methods.mapCenter(); + settings.map.zoomOut(); + }, + + // center from the map menu + mapCenter: function(){ + $('#chimere_map_menu').hide(); + settings.map.setCenter(settings.current_position); + }, + + // set current position + setCurrentPosition: function(lonlat){ + settings.current_position = lonlat; + }, + zoomOnCluster: function(feature){ + if(!feature.cluster) // if not cluster + { + feature.attributes.marker.events.triggerEvent('click'); + feature.attributes.marker.events.triggerEvent('mouseover'); + feature.attributes.marker.events.triggerEvent('mouseout'); + } else { + methods.zoomIn(); + settings.map.setCenter( + feature.geometry.getBounds().getCenterLonLat()); + } + }, /* + * Display menu on the map + */ + displayMapMenu: function(e) { + if (methods.hidePopup(e)) return; + if ($('#chimere_map_menu').is(":visible")){ + $('#chimere_map_menu').hide(); + } else{ + methods.setCurrentPosition( + settings.map.getLonLatFromViewPortPx(e.xy)); + var offsetX = e.pageX; + var offsetY = e.pageY; + $('#chimere_map_menu').show('fast'); + $('#chimere_map_menu').css('display', 'block'); + $('#chimere_map_menu').css('top', offsetY); + $('#chimere_map_menu').css('left', offsetX); + } + }, + /* * Load markers and route from DB */ loadGeoObjects: function () { @@ -237,30 +545,44 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (!ids) ids = '0'; var uri = extra_url + "getGeoObjects/" + ids; if (settings.display_submited) uri += "/A_S"; - $.ajax({url: uri, + $.ajax({url: uri, dataType: "json", success: function (data) { settings.layerMarkers.clearMarkers(); settings.layerVectors.removeAllFeatures(); + if (settings.enable_clustering){ + settings.cluster_array = []; + settings.layerCluster.removeAllFeatures(); + } for (var i = 0; i < data.features.length; i++) { var feature = data.features[i]; if (feature.geometry.type == 'Point'){ methods.addMarker(feature); } else if (feature.geometry.type == 'LineString') { methods.addRoute(feature); + } else if (feature.geometry.type == 'MultiLineString') { + methods.addMultiLine(feature); } } + if (settings.enable_clustering){ + settings.layerCluster.addFeatures( + settings.cluster_array); + methods.cleanCluster(); + } + settings.map.resetLayersZIndex(); }, - error: function (data) { + error: function (data, textStatus, errorThrown) { settings.layerMarkers.clearMarkers(); settings.layerVectors.removeAllFeatures(); + if (settings.enable_clustering){ + settings.layerCluster.removeAllFeatures(); + } }, complete: function () { if($('#waiting').length){$('#waiting').hide();} } }); }, - /* * Update the categories div in ajax */ @@ -276,9 +598,11 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { uri += "getAvailableCategories/"; var params = {"current_extent": current_extent} if (settings.display_submited) params["status"] = "A_S"; - $.ajax({url: uri, - data: params, + $.ajax({url: uri, + data: params, + cache: false, success: function (data) { + $('#categories').empty(); $('#categories').html(data); _init_categories(); _reCheckCategories(); @@ -295,7 +619,13 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { category_element.parent().find("li input").attr("checked", val); } var _toggle_categories = function (subcategory_element) { - var parent = subcategory_element.parent().parent().parent(); + var parent = subcategory_element.closest('ul'); + var parent_label = parent.parent().find("> span"); + if (parent.find('input[type=checkbox]:checked').length){ + parent_label.addClass('category-selected'); + } else { + parent_label.removeClass('category-selected'); + } var master_check = parent.find("> input"); if (parent.find('.subcategories input[type=checkbox]').length == parent.find('.subcategories input[type=checkbox]:checked').length){ @@ -303,32 +633,66 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } else { master_check.removeAttr('checked'); } + + if($('#action-categories').length){ + if ($('#categories input[type=checkbox]:checked').length){ + $('#action-categories').addClass('category-selected'); + } else { + $('#action-categories').removeClass('category-selected'); + } + } return master_check; }; var _init_categories = function () { /* * Add event listener in categories DOM elements */ - $('#categories #ul_categories > li > input').bind("click", function () { - methods.hidePopup(); + $('#categories #ul_categories > li > input').bind("click", + function (e) { + methods.hidePopup(e); _toggle_subcategories($(this)); methods.loadGeoObjects(); settings.permalink.updateLink(); }); - $('.subcategories li input').bind("click", function () { - methods.hidePopup(); + $('.subcategories li input').bind("click", function (e) { + var c_name = $(this).attr('name'); + c_name = c_name.substr(c_name.lastIndexOf("_")+1); + if($(this).is(':checked')){ + methods.subcategory_detail(c_name); + } + var par = $(this).parent(); + if ($(this).attr('checked')){ + par.addClass('selected'); + } else { + par.removeClass('selected'); + } + methods.hidePopup(e); methods.loadGeoObjects(); _toggle_categories($(this)); settings.permalink.updateLink(); + if ($('#layer_cat_'+c_name).length){ + $('#layer_cat_'+c_name).prop("checked", + this.checked); + } }); $('#display_submited_check').bind("click", function () { methods.loadGeoObjects(); settings.permalink.updateLink(); }); // Zoom to category - $(".zoom_to_category").bind("click", function (e) {var id = this.id.substr(this.id.lastIndexOf("_")+1); helpers.zoom_to_category(id);}); - $(".zoom_to_subcategory").bind("click", function (e) {var id = this.id.substr(this.id.lastIndexOf("_")+1); helpers.zoom_to_subcategories([id]);}); - $(".toggle_category").bind("click", function (e) {var id = this.id.substr(this.id.lastIndexOf("_")+1); methods.toggle_category(id); }); + $(".zoom_to_category").bind("click", function (e) { + var id = this.id.substr(this.id.lastIndexOf("_")+1); + helpers.zoom_to_category(id); + }); + $(".zoom_to_subcategory").bind("click", function (e) { + var id = this.id.substr(this.id.lastIndexOf("_")+1); + helpers.zoom_to_subcategories([id]); + }); + $(".toggle_category").parent().bind("click", function (e) { + var item = $(this).children('.toggle_category'); + var id = item.attr('id').substr(item.attr('id').lastIndexOf("_")+1); + methods.toggle_category(id); + }); } var _reCheckCategories = function (){ /* recheck categories on init or when a redraw occurs */ @@ -351,6 +715,37 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } }, /* + * Hide clusterized markers + */ + cleanCluster: function (){ + if (settings.map.getZoom() === 18) { + // Don't cluster at this level. No matter what. + settings.clustering.threshold = 1000; + } else { + settings.clustering.threshold = 2; + } + //settings.layerCluster.refresh({force:true}); + settings.clustering.recluster(); + var hidden_feature_idx = []; + if (settings.map.getZoom() != 18) { + for(var idx=0; idx<settings.layerCluster.features.length; idx++){ + if(settings.layerCluster.features[idx].cluster){ + for(var c=0;c < settings.layerCluster.features[idx].cluster.length; c++) { + hidden_feature_idx.push( + settings.layerCluster.features[idx].cluster[c].attributes.pk); + } + } + } + } + for(j=0; j<settings.layerMarkers.markers.length;j++){ + if(hidden_feature_idx.indexOf(settings.layerMarkers.markers[j].pk) > -1){ + settings.layerMarkers.markers[j].display(false); + } else { + settings.layerMarkers.markers[j].display(true); + } + } + }, + /* * Put a marker on the map */ addMarker: function (mark) { @@ -362,24 +757,37 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { var lon = mark.geometry.coordinates[0]; var size = new OpenLayers.Size(mark.properties.icon_width, mark.properties.icon_height); - var iconclone = new OpenLayers.Icon(MEDIA_URL + mark.properties.icon_path, - size, settings.icon_offset); + var icon_url = MEDIA_URL + mark.properties.icon_path; + var icon_hover_url = ''; + if (mark.properties.icon_hover_path){ + var icon_hover_url = MEDIA_URL + mark.properties.icon_hover_path; + } + var iconclone = new OpenLayers.Icon(icon_url, size, + settings.icon_offset); + var feature = new OpenLayers.Feature(settings.layerMarkers, - new OpenLayers.LonLat(lon, lat).transform(EPSG_DISPLAY_PROJECTION, - EPSG_PROJECTION), + new OpenLayers.LonLat(lon, lat).transform( + EPSG_DISPLAY_PROJECTION, + EPSG_PROJECTION), {icon:iconclone}); feature.pk = mark.properties.pk; - feature.popupClass = OpenLayers.Popup.FramedCloud; + feature.popupClass = settings.popupClass; feature.data.popupContentHTML = "<div class='cloud'>"; - feature.data.popupContentHTML += mark.properties.name; + if (!settings.popupContentFull) { + feature.data.popupContentHTML += mark.properties.name; + } feature.data.popupContentHTML += "</div>"; feature.data.overflow = 'hidden'; var marker = feature.createMarker(); + marker.pk = feature.pk; + marker.icon_url = icon_url; + marker.icon_hover_url = icon_hover_url; + marker.category_name = mark.properties.category_name; /* manage markers events */ var _popup = function() { /* show the popup */ if (settings.current_popup != null) { - settings.current_popup.hide(); + settings.current_popup.hide(); } if (feature.popup == null) { feature.popup = feature.createPopup(); @@ -389,42 +797,101 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } settings.current_popup = feature.popup; /* hide on click on the cloud */ - settings.current_popup.groupDiv.onclick = methods.hidePopup; + if (!settings.explicit_popup_hide){ + settings.current_popup.groupDiv.onclick = methods.hidePopup; + } settings.permalink.updateLink(); } + var _repan_popup = function(){ + /* re-pan manually */ + + // no clean way to detect if all the element are ready + // lack of better... + setTimeout( + function(){ + settings.current_popup.panIntoView(); + }, 1000); + } + var markerClick = function (evt) { settings.current_feature = feature; + methods.setCurrentPosition(feature.lonlat); if ( settings.on_marker_click ) { settings.on_marker_click(evt, mark, settings); } else { + methods.center_on_feature(); + $('#chimere_map_menu').hide(); // Default popup if (feature.popup && feature.popup.visible()) { if (settings.current_popup == feature.popup) { feature.popup.hide(); if (!settings.simple){ - $('#panel').removeClass('panel-minified'); $('#detail').hide(); } } else { settings.current_popup.hide(); _popup(); methods.display_feature_detail(feature.pk); + _repan_popup(); } } else { _popup(); methods.display_feature_detail(feature.pk); + _repan_popup(); } } OpenLayers.Event.stop(evt); }; var markerOver = function (evt) { document.body.style.cursor='pointer'; + if (settings.current_feature && settings.current_feature.popup + && settings.current_feature.popup.visible()) return; + var marker = evt.object; + if (marker.icon_hover_url){ + marker.setUrl(marker.icon_hover_url); + } + px = settings.map.getPixelFromLonLat(marker.lonlat); + marker_hover = $('#'+settings.marker_hover_id); + marker_hover_content = $('#'+settings.marker_hover_content_id); + marker_hover_content.html(marker.category_name); + var map_position = $(settings.map.div).offset(); + + var width = marker_hover.width(); + width += parseInt(marker_hover.css("padding-left"), 10) + + parseInt(marker_hover.css("padding-right"), 10) + + parseInt(marker_hover.css("margin-left"), 10) + + parseInt(marker_hover.css("margin-right"), 10) + + parseInt(marker_hover.css("borderLeftWidth"), 10) + + parseInt(marker_hover.css("borderRightWidth"), 10); + var pos_x = px.x + map_position.left + - width/2 + 1; + if (settings.marker_hover_offset) + pos_x += settings.marker_hover_offset.x; + $('#'+settings.marker_hover_id).css('left', pos_x); + var height = marker_hover.height(); + height += parseInt(marker_hover.css("padding-top"), 10) + + parseInt(marker_hover.css("padding-bottom"), 10) + + parseInt(marker_hover.css("margin-top"), 10) + + parseInt(marker_hover.css("margin-bottom"), 10) + + parseInt(marker_hover.css("borderBottomWidth"), 10) + + parseInt(marker_hover.css("borderTopWidth"), 10); + var pos_y = px.y + map_position.top + - height - marker.icon.size.h; + if (settings.marker_hover_offset) + pos_y += settings.marker_hover_offset.y; + $('#'+settings.marker_hover_id).css('top', pos_y); + $('#'+settings.marker_hover_id).show(); OpenLayers.Event.stop(evt); }; var markerOut = function (evt) { document.body.style.cursor='auto'; + var marker = evt.object; + if (marker.icon_hover_url){ + marker.setUrl(marker.icon_url); + } + $('#'+settings.marker_hover_id).hide(); OpenLayers.Event.stop(evt); }; marker.events.register('click', feature, markerClick); @@ -433,13 +900,29 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.layerMarkers.addMarker(marker); /* show the item when designed in the permalink */ if (settings.display_feature == feature.pk){ + settings.current_feature = feature; _popup(feature); methods.display_feature_detail(feature.pk); if (!settings.display_route){ settings.map.setCenter(feature.lonlat, 16); - methods.loadCategories(); + _repan_popup(); } + settings.display_feature = null; + //methods.loadCategories(); + } + + if (settings.enable_clustering){ + // manage cluster layer + var point = new OpenLayers.Geometry.Point(lon, lat).transform( + EPSG_DISPLAY_PROJECTION, + EPSG_PROJECTION); + var feat = new OpenLayers.Feature.Vector(point); + feat.attributes = { icon: MEDIA_URL + mark.properties.icon_path, + name: "", label:"", pk:mark.properties.pk, + marker:marker}; + settings.cluster_array.push(feat); } + return feature; }, @@ -459,7 +942,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.current_feature = new OpenLayers.Feature.Vector(); var style = OpenLayers.Util.extend({}, - OpenLayers.Feature.Vector.style['default']); + OpenLayers.Feature.Vector.style['default']); style.strokeColor = route.properties.color; style.strokeWidth = 3; settings.current_feature.style = style; @@ -471,6 +954,307 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { methods.loadCategories(); } }, + /* + * Put a multiline on the map + */ + addMultiLine: function(feature) { + var gformat = new OpenLayers.Format.GeoJSON(); + var feats = gformat.read(feature); + var style = OpenLayers.Util.extend({}, + OpenLayers.Feature.Vector.style['default']); + style.strokeColor = feature.properties.color; + style.strokeWidth = 2; + feats[0].style = style; + feats[0].geometry = feats[0].geometry.transform( + EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()); + settings.layerVectors.addFeatures(feats); + }, + routingInputChange: function(nominatim_id){ + $('#map_menu_clear').show(); + switch(nominatim_id){ + case 'nominatim_start': + settings.routing_start = new OpenLayers.Marker( + new OpenLayers.LonLat( + $('#'+nominatim_id+'_lon').val(), + $('#'+nominatim_id+'_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + break; + case 'nominatim_end': + settings.routing_end = new OpenLayers.Marker( + new OpenLayers.LonLat( + $('#'+nominatim_id+'_lon').val(), + $('#'+nominatim_id+'_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + break; + default: + settings.routing_steps.push(new OpenLayers.Marker( + new OpenLayers.LonLat( + $('#'+nominatim_id+'_lon').val(), + $('#'+nominatim_id+'_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_step.clone())); + settings.layerRouteMarker.addMarker( + settings.routing_steps[settings.routing_steps.length-1]); + break; + } + if (settings.routing_end && settings.routing_start + && $('#search_routing').length) { + $('#search_routing').button('enable'); + } + }, + + redrawRoutingIcons: function(){ + settings.layerRouteMarker.clearMarkers(); + settings.layerRouteMarker.addMarker(settings.routing_start); + settings.layerRouteMarker.addMarker(settings.routing_end); + for (var k=0;k<settings.routing_steps.length;k++){ + settings.layerRouteMarker.addMarker(settings.routing_steps[k]); + } + }, + + // set the start point for routing + routingFrom: function(){ + $('#chimere_map_menu').hide(); + settings.routing_panel_open(); + $('#map_menu_clear').show(); + settings.routing_start = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + if (nominatim_url){ + helpers.updateNominatimName(settings.current_position.clone() + .transform(settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION), + 'start_label'); + } + if (settings.routing_end) methods.route(); + }, + // add a step point for routing + routingAddStep: function(){ + $('#chimere_map_menu').hide(); + settings.routing_panel_open(); + $('#map_menu_clear').show(); + settings.routing_steps.push(new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_step.clone())); + settings.layerRouteMarker.addMarker( + settings.routing_steps[settings.routing_steps.length-1]); + + if (nominatim_url){ + var current_itinerary_number = methods.add_step_fx(); + helpers.updateNominatimName(settings.current_position.clone() + .transform(settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION), + 'step_'+current_itinerary_number+'_label'); + } + if (settings.routing_end && settings.routing_start) methods.route(); + }, + + // add a step on the interface + add_step_fx: function (){ + settings.itinerary_step_number += 1; + var cloned = $("#id_start_div").clone(); + var c_id = 'step_' + settings.itinerary_step_number; + cloned.attr('id', 'id_'+c_id+'_div'); + cloned.children('label').html(step_label).addClass('step_label'); + cloned.children("#nominatim_start_label").attr('id', c_id+'_label' + ).html(''); + cloned.children('label.nominatim-label').attr('for', "" + ).removeClass('step_label'); + var id_suffixes = ['_lat', '_lon', '']; + for (idx=0;idx < id_suffixes.length;idx+=1){ + var suffix = id_suffixes[idx]; + val = c_id + suffix; + cloned.children("#nominatim_start"+suffix).attr('id', val + ).attr('name', val); + } + if (settings.itinerary_step_number == 1){ + $("#nominatim_end_label").after(cloned); + } else { + $("#step_"+(settings.itinerary_step_number-1)+"_label" + ).after(cloned); + } + $('#' + c_id).val(default_nominatim_lbl); + $('#' + c_id).click(function(){ + $('#'+c_id).val(''); + }); + $(".nominatim-widget").autocomplete(nominatim_widget_options); + return settings.itinerary_step_number; + }, + + // set the finish point for routing + routingTo: function(){ + $('#chimere_map_menu').hide(); + settings.routing_panel_open(); + $('#map_menu_clear').show(); + settings.routing_end = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + if (nominatim_url){ + helpers.updateNominatimName(settings.current_position.clone() + .transform(settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION), + 'end_label'); + } + if (settings.routing_start) methods.route(); + }, + + // clear the current itinerary + routingClear: function(){ + $('#nominatim_start_lon').val(''); + $('#nominatim_start_lat').val(''); + $('#nominatim_start_label').html(''); + $('#chimere_start_label').html(''); + $('#nominatim_end_lon').val(''); + $('#nominatim_end_lat').val(''); + $('#nominatim_end_label').html(''); + $('#chimere_end_label').html(''); + $('.nominatim-widget').val(default_nominatim_lbl); + $('#chimere_map_menu').hide(); + $('#map_menu_clear').hide(); + $('#chimere_itinerary').hide(); + $('#chimere_itinerary_form').show(); + $('div[id^="id_step_"]').remove(); + if($('#search_routing').length) $('#search_routing').button('disable'); + settings.layerRoute.removeAllFeatures(); + settings.layerRouteMarker.clearMarkers(); + settings.routing_start = null; + settings.routing_end = null; + settings.routing_steps = new Array(); + settings.current_itinerary_number = 0; + settings.current_route_feature = null; + settings.permalink.updateLink(); + }, + // display a route + route: function(){ + if($('#search_routing').length) $('#search_routing').button('enable'); + if (!settings.routing_start || !settings.routing_end){ + return; + } + var steps = [settings.routing_start.lonlat.clone()] + for (var i = 0; i < settings.routing_steps.length; i++) { + steps.push(settings.routing_steps[i].lonlat.clone()); + } + steps.push(settings.routing_end.lonlat.clone()); + // create the appropriate URL + var uri = extra_url + "route/" + var transport = $('input[name=transport]:checked').val(); + if(transport){ + uri += transport + "/" + } + var speed = $('#id_speed option:selected').val(); + if(!speed){ + var speed = $('input[name=speed]:checked').val(); + } + if(speed){ + uri += speed.split('_')[1] + "/" + } + for (var i = 0; i < steps.length; i++) { + var step = steps[i].transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + if (i > 0){ + uri += '_'; + } + uri += step.lon + '_' + step.lat; + } + settings.permalink.updateLink(); + $.ajax({url: uri, + dataType: "json", + success: function (data) { + settings.layerRoute.removeAllFeatures(); + methods.redrawRoutingIcons(); + methods.hideMessage(); + if (!data.features.length){ + methods.displayMessage(routing_fail_message); + return; + } + for (var i = 0; i < data.features.length; i++) { + var feat = data.features[i]; + if(feat.type == 'LineString'){ + settings.current_route_feature = + methods.putRoute(feat); + } else { + var lonlat = new OpenLayers.LonLat( + feat.geometry.coordinates[0], + feat.geometry.coordinates[1]); + lonlat.transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()); + var icon_height = feat.properties.icon_height; + var icon_width = feat.properties.icon_width; + var marker = new OpenLayers.Marker(lonlat, + new OpenLayers.Icon( + feat.properties.icon_path, + new OpenLayers.Size(icon_width, + icon_height), + new OpenLayers.Pixel( + -(icon_width/2), + -icon_height)) + ); + settings.layerRouteMarker.addMarker(marker); + } + } + if (data.message) methods.displayMessage(data.message); + settings.map.zoomToExtent( + settings.layerRoute.getDataExtent()); + settings.map.zoomOut(); + $('#id_transport_it').find('span' + ).removeClass('selected'); + $('#id_transport_it_'+data.properties.transport + ).addClass('selected'); + $('#chimere_total_label').html( + data.properties.total); + $('#chimere_itinerary_content').html( + data.properties.description); + $('#chimere_itinerary').show(); + if(!settings.edition_type_is_route){ + $('#chimere_itinerary_form').hide(); + settings.routing_panel_open(); + } else { + methods.updateRoutingInput(); + } + }, + error: function (jqXHR, textStatus, errorThrown) { + methods.redrawRoutingIcons(); + methods.hideMessage(); + console.log(errorThrown); + console.log(textStatus); + settings.layerRoute.removeAllFeatures(); + methods.displayMessage(routing_fail_message); + } + }); + + }, + /* + Put a route on the map + */ + putRoute: function(polyline) { + var point_array = new Array(); + for (i=0; i<polyline.coordinates.length; i++){ + var point = new OpenLayers.Geometry.Point(polyline.coordinates[i][0], + polyline.coordinates[i][1]); + point_array.push(point); + } + var linestring = new OpenLayers.Geometry.LineString(point_array); + linestring.transform(EPSG_DISPLAY_PROJECTION, settings.map.getProjectionObject()); + current_route = new OpenLayers.Feature.Vector(); + var style = OpenLayers.Util.extend({}, + OpenLayers.Feature.Vector.style['default']); + style.strokeWidth = 3; + current_route.style = style; + current_route.geometry = linestring; + settings.layerRoute.addFeatures([current_route]); + return current_route; + }, display_feature_detail: function (pk) { /* * update current detail panel with an AJAX request @@ -480,25 +1264,34 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { uri += "getDetail/" + pk; var params = {} if (settings.simple) { params["simple"] = 1; } - $.ajax({url: uri, - data: params, + $.ajax({url: uri, + data: params, + dataType: "html", success: function (data) { - if ( settings.display_feature_detail_fx ) { - // Custom function ? - settings.display_feature_detail_fx(data, settings); + if ( settings.display_feature_detail_fx ) { + // Custom function ? + settings.display_feature_detail_fx(data, settings); + } + else { + if (!settings.popupContentFull) { + $('#detail').html(data).show(); } else { - if (!settings.simple) { - $('#panel').addClass('panel-minified'); - $('#detail').html(data).show(); - } - else { - settings.current_popup.setContentHTML("<div class='cloud'>" + data + "</div>"); - } + settings.current_popup.setContentHTML("<div class='cloud'>" + data + "</div>"); } } + } }); }, + displayMessage: function(message){ + if (!$('#chimere_message').length) return; + $('#chimere_message').html(message); + $('#chimere_message').dialog('open'); + }, + hideMessage: function(message){ + if (!$('#chimere_message').length) return; + $('#chimere_message').dialog('close'); + }, center_on_feature: function(feature) { var f = get_or_set(feature, settings.current_feature); if (f) @@ -520,28 +1313,64 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { var uri = extra_url + "getDescriptionDetail/" + category_id; $.ajax({url:uri, success: function (data) { - $("#category_detail").html(data).dialog(); - $("#category_detail").dialog( "option", "title", + $("#category_description").html(data).dialog(); + $("#category_description").dialog( "option", "title", $("#category_title").html()); } }); }, + /* + * Load the subcategory description if available + */ + subcategory_detail: function(category_id){ + var uri = extra_url + "getCategory/" + category_id; + + $.ajax({url: uri, + dataType: "json", + success: function (data) { + if (!data.description){return} + $('#category_description').html(data.description); + $("#category_description").dialog("option", "title", + data.name); + $('#category_description').dialog('open'); + }, + error: function (data) { + // fail silently + } + }); + }, toggle_category: function (id) { // TODO make this id DOM element customisable // Check if element is currently visible or not var was_visible = $("#maincategory_" + id).is(":visible"); // Close all categories - $("#categories ul.subcategories").hide(); + var category_plus = STATIC_URL + "chimere/img/plus.png"; + var category_minus = STATIC_URL + "chimere/img/minus.png"; + if (settings.category_accordion){ + $("#categories ul.subcategories").hide(); + $("#categories img.toggle_category").attr("src", category_plus); + $("#categories .main_category").addClass("toggle_plus"); + $("#categories .main_category").removeClass("toggle_minus"); + } // Put a minus image - $("#categories img.toggle_category").attr("src", STATIC_URL + "chimere/img/plus.png"); if (!was_visible) { // Show the subcategories $("#maincategory_" + id).toggle(); + $("#maincategory_" + id).parent().addClass("toggle_minus"); + $("#maincategory_" + id).parent().removeClass("toggle_plus"); // Put a plus image - $("#maincategory_img_" + id).attr("src", STATIC_URL + "chimere/img/minus.png"); + $("#maincategory_img_" + id).attr("src", category_minus); settings.current_category = id; } + if (!settings.category_accordion && was_visible) + { + $("#maincategory_" + id).toggle(); + $("#maincategory_" + id).parent().addClass("toggle_plus"); + $("#maincategory_" + id).parent().removeClass("toggle_minus"); + // Put a minus image + $("#maincategory_img_" + id).attr("src", category_plus); + } }, zoomToCurrentExtent: function(){ /* zoom to current extent */ @@ -573,17 +1402,13 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { }, /* put the marker on the map and update latitude and longitude fields */ putEditMarker: function (lonlat, zoom){ - if (settings.current_feature) { - settings.layerMarkers.removeMarker(settings.current_feature); + if (settings.current_edit_feature) { + settings.layerMarkers.removeMarker(settings.current_edit_feature); } - settings.current_feature = new OpenLayers.Marker(lonlat.clone(), + settings.current_edit_feature = new OpenLayers.Marker(lonlat.clone(), settings.default_icon); - settings.layerMarkers.addMarker(settings.current_feature); - lonlat = lonlat.clone().transform(settings.map.getProjectionObject(), - EPSG_DISPLAY_PROJECTION); - $('#id_point').val('POINT(' + lonlat.lon + ' ' + lonlat.lat + ')'); - $('#live_latitude').val(lonlat.lat); - $('#live_longitude').val(lonlat.lon); + settings.layerMarkers.addMarker(settings.current_edit_feature); + methods.updateMarkerInput(); /* zoom to the point */ if (zoom){ var bounds = settings.layerMarkers.getDataExtent(); @@ -591,6 +1416,28 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } return; }, + updateMarkerInput: function(){ + if (!settings.current_edit_feature) { + return; + } + lonlat = settings.current_edit_feature.lonlat.clone().transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + $('#id_point').val('POINT(' + lonlat.lon + ' ' + lonlat.lat + ')'); + if($('#live_latitude').length){ + $('#live_latitude').val(lonlat.lat); + $('#live_longitude').val(lonlat.lon); + } + + }, + updateRoutingInput: function(){ + if (!settings.current_route_feature) { + return; + } + var current_geo = settings.current_route_feature.geometry.clone(); + current_geo.transform(EPSG_PROJECTION, EPSG_DISPLAY_PROJECTION); + jQuery('#id_route').val(current_geo); + }, activateCurrentControl: function(){ if (settings.current_control){ settings.current_control.activate(); @@ -646,19 +1493,25 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (bounds) settings.map.zoomToExtent(bounds); }, hidePopup: function (evt) { + $('#'+settings.marker_hover_id).hide(); if (settings.hide_popup_fx) { settings.hide_popup_fx(evt, settings) } else { // Default behaviour if (settings.current_popup) { - settings.current_popup.hide(); if (!settings.simple){ - $('#panel').removeClass('panel-minified'); $('#detail').hide(); } + if (settings.current_popup.visible()){ + settings.current_popup.hide(); + if(evt) + settings.map.events.triggerEvent('click', evt); + return true; + } } } + return false; }, saveExtent: function(){ var extent_key = 'MAP_EXTENT'; @@ -794,8 +1647,23 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (vertices){ jQuery('#id_point').val(vertices); } + }, + updateNominatimName:function(lonlat, response_id){ + $.ajax({ + url: nominatim_url.substring(0, nominatim_url.length-6) + 'reverse', + data: { + format: "json", + lat:lonlat.lat, + lon:lonlat.lon + }, + dataType:'json', + success: function (vals) { + $('#'+response_id).html(vals.display_name); + $('#nominatim_'+response_id).html(vals.display_name); + $('#chimere_'+response_id).html(vals.display_name); + } + }); } - }; // End of helpers $.fn.chimere = function (thing) { @@ -822,7 +1690,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { else { $.error( 'Method ' + thing + ' does not exist on jQuery.chimere' ); } - return this; }; })( jQuery ); diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js new file mode 100644 index 0000000..99f7034 --- /dev/null +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -0,0 +1,46 @@ +var default_nominatim_lbl = ''; +var nominatim_widget_options = { + source: function (request, response) { + $.ajax({ + url: nominatim_url, + data: { + format: "json", + q: request.term, + }, + dataType:'json', + success: function ( data ) { + response ( $.map(data, function(item) { + return { + label: item.display_name, + value: item.display_name, + lat: item.lat, + lon: item.lon + } + })); + + } + }) + }, + minLength: 6, + delay: 1000, + select: function ( event, ui ) { + $('#'+$(this).attr('id')+'_lat').val(ui.item.lat); + $('#'+$(this).attr('id')+'_lon').val(ui.item.lon); + $('#'+$(this).attr('id')+'_label').html(ui.item.label); + $('#chimere_'+$(this).attr('id').substring(10)+'_label').html( + ui.item.label); + $('#'+$(this).attr('id')).val(default_nominatim_lbl); + jQuery("#map").chimere("routingInputChange", $(this).attr('id')); + return false; + }, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } +} + +$(function(){ + $(".nominatim-widget").autocomplete(nominatim_widget_options); +}); diff --git a/chimere/static/chimere/js/routing-widget.js b/chimere/static/chimere/js/routing-widget.js new file mode 100644 index 0000000..34ca46c --- /dev/null +++ b/chimere/static/chimere/js/routing-widget.js @@ -0,0 +1,47 @@ +var step_label = "Step"; +var add_step = null; + +$(document).ready(function() { + var itinerary_step_number = 0; + $("#add_step_link").click(function(){ + $('#main-map').chimere('add_step_fx'); + return false; + }); + $('#search_routing').button({'disabled':true}); + $('#routing_button').click(function(){ + $('#chimere_itinerary_panel').dialog('open'); + }); + $('#chimere_itinerary_modify').click(function(){ + $('#chimere_itinerary').hide(); + $('#chimere_itinerary_form').show(); + }); + $('#chimere_itinerary_new').click(function(){ + $('#map').chimere('routingClear'); + }); + $('#search_routing').click(function(){ + $('#map').chimere('route'); + }); + + var detached_speeds = Array(); + function filter_speed(transport){ + $("#id_speed_div").show(); + for (i=0;i<detached_speeds.length;i+=1){ + $("#id_speed_div ul").append(detached_speeds[i]); + } + detached_speeds = Array(); + $("#id_speed_div input[type=radio]").each(function(){ + if(!$(this).val().match(transport) && $(this).val()){ + detached_speeds.push($(this).parent().parent().detach()); + } + }); + $('#id_speed_div').val(''); + if($("#id_speed_div input[type=radio]").length == 1){ + $("#id_speed_div").hide(); + } + } + $('#id_transport label').click(function(){ + checked_item = $("#"+$(this).attr('for')); + filter_speed(checked_item.val()); + }); + filter_speed($('#id_transport :checked').val()); +}); diff --git a/chimere/static/chimere/js/utils.js b/chimere/static/chimere/js/utils.js index 80ab91a..460e843 100644 --- a/chimere/static/chimere/js/utils.js +++ b/chimere/static/chimere/js/utils.js @@ -236,6 +236,12 @@ function has_index(index, arr) { function get_or_set(v, d){ return typeof v === "undefined" ? d : v;} +/* email validity */ +function isValidEmailAddress(emailAddress) { + var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i); + return pattern.test(emailAddress); +}; + /* remove multiple, leading or trailing spaces */ function trim(s) { s = s.replace(/(^\s*)|(\s*$)/gi,""); diff --git a/chimere/tasks.py b/chimere/tasks.py index a74dce8..02e32a4 100644 --- a/chimere/tasks.py +++ b/chimere/tasks.py @@ -33,7 +33,7 @@ from external_utils import OsmApi def single_instance_task(timeout): def task_exc(func): def wrapper(*args, **kwargs): - return func() + return func(*args, **kwargs) return wrapper return task_exc diff --git a/chimere/templates/base.html b/chimere/templates/base.html index 2a50fc3..619aa0b 100644 --- a/chimere/templates/base.html +++ b/chimere/templates/base.html @@ -2,30 +2,30 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> - <title>{% block title %}Chimère{% endblock %}</title> + <title>{% block title %}{{PROJECT_NAME}}{% endblock %}</title> {% block extra_head %} {% endblock %} </head> <body {% block body_id %}{% endblock %} {% block body_class %}{% endblock %}> - {% block extrabody %} +{% block extrabody %} +{% endblock %} +{% block body %} +<div id="header"> + {% block header %} {% endblock %} - {% block body %} - <div id="header"> - {% block header %} - {% endblock %} - </div> - <div id="sidebar"> - {% block sidebar %} - {% endblock %} - </div> - <div id="content"> - {% block content %} - {% endblock %} - </div> - <div id="footer"> - {% block footer %} - {% endblock %} - </div> +</div> +<div id="sidebar"> + {% block sidebar %} {% endblock %} +</div> +<div id="content"> + {% block content %} + {% endblock %} +</div> +<div id="footer"> + {% block footer %} + {% endblock %} +</div> +{% endblock %} </body> </html> diff --git a/chimere/templates/chimere/base.html b/chimere/templates/chimere/base.html index a1a0b39..620c84f 100644 --- a/chimere/templates/chimere/base.html +++ b/chimere/templates/chimere/base.html @@ -2,6 +2,7 @@ {% load chimere_tags i18n %} {% block extra_head %} <link rel="stylesheet" href="{{ STATIC_URL }}chimere/css/styles.css" /> +<link rel="stylesheet" href="{{ STATIC_URL }}chimere/css/print.css" media='print'/> {% if css_area %} <link rel="stylesheet" href="{{ css_area }}" />{% endif %} {% endblock %} diff --git a/chimere/templates/chimere/blocks/actions.html b/chimere/templates/chimere/blocks/actions.html index 2806321..93debb0 100644 --- a/chimere/templates/chimere/blocks/actions.html +++ b/chimere/templates/chimere/blocks/actions.html @@ -2,7 +2,7 @@ <ul id='action' class='action'> {% for action, subactions in actions %} <li class='ui-widget ui-button ui-state-default ui-corner-all {% ifequal action.id action_selected.0 %} ui-state-active{% endifequal %}'> - <a href='{{extra_url}}{{ action.path }}' onclick='jQuery("#map").chimere("saveExtent");'>{{ action.label }}</a> + <a href='{{ action.url }}' onclick='jQuery("#map").chimere("saveExtent");'>{{ action.label }}</a> </li> {% endfor %} </ul> @@ -11,7 +11,7 @@ {% ifequal action.id action_selected.0 %}{% if subactions %} {% for subaction in subactions %} <li class='ui-widget ui-button ui-state-default ui-corner-all{% ifequal subaction.id action_selected.1 %} ui-state-active{% endifequal %}'> - <a href='{{extra_url}}{{ subaction.path }}' onclick='saveExtent();'>{{ subaction.label }}</a> + <a href='{{ subaction.url }}' onclick='saveExtent();'>{{ subaction.label }}</a> </li> {% endfor %} {% endif %}{% endifequal %} diff --git a/chimere/templates/chimere/blocks/alternate_multimedia.html b/chimere/templates/chimere/blocks/alternate_multimedia.html index 0662750..50bddd5 100644 --- a/chimere/templates/chimere/blocks/alternate_multimedia.html +++ b/chimere/templates/chimere/blocks/alternate_multimedia.html @@ -14,13 +14,14 @@ {% for formset in formsets %} {% for frm in formset%} {% if not forloop.last %} - <li> + <li class='{% if forloop.parentloop.counter0 %}picture{%else%}multimedia{%endif%}'> {%if forloop.first %}{% for hidden in frm.hidden_fields %} {{ hidden }} {% endfor %}{% endif %} {% for field in frm.visible_fields %} {% if field.name == "name" %} - <span class='value'>{{ field.field.value }}</span> + <span class='value'>{{ field.value }}</span> + <img class='remove-media' alt='Remove media' src='{{STATIC_URL}}chimere/img/close.png'/> {% endif %} <span class='hidden'>{{field}}</span> {% endfor %} @@ -31,7 +32,7 @@ </ul> <button id='add_multimedia_list'>{% trans "Add" %}</button> </div> - <div id='multimedia_form' title="{% trans "Add multimedia from your computer or a site"%}"> + <div id='multimedia_form' title="{% trans "Add multimedia from your computer or a website"%}"> <div class='notice'>{% trans "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." %} </div> <div class="fieldWrapper"> @@ -51,6 +52,9 @@ </div> <script text='text/javascript'> $(function(){ + $(".remove-media").click(function(){ + $(this).parents('li').remove(); + }); var current_image_number = 0; var current_multi_number = 0; $("#multimedia_form").dialog({autoOpen:false, @@ -110,20 +114,33 @@ content += '<input type="hidden" name="'+prefix+'-DELETE" value=""/>\n'; content += '<input type="hidden" name="'+prefix+'-name" value="'+ $("#multimedia_name").val() +'"/>\n'; content += $("#multimedia_name").val(); - content += " <img class='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 += " <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() && $("#picture-"+current_image_number+"-picture").val()){ - // the file item cannot be recopied - security issue - // so it is hiden then a new one is added - //$('#picture-'+current_image_number+'-picture').hide(); + // the file field cannot be recopied - security issue + // so it is moved var file_item = $('#picture-'+current_image_number+'-picture'); - //var cloned = file_item.clone(true); - //file_item.hide(); - //cloned.insertAfter(file_item); + var cloned = file_item.clone(true); + file_item.hide(); + cloned.insertAfter(file_item); file_item.appendTo($("#multimedia_list_content li").last()); + current_image_number += 1; + cloned.attr('id', 'picture-'+current_image_number+'-picture'); + cloned.attr('name', 'picture-'+current_image_number+'-picture'); + cloned.val(''); + $('#id_picture-TOTAL_FORMS').val(current_image_number + 1); + } else { + current_multi_number += 1; + $('#id_multimedia-TOTAL_FORMS').val(current_multi_number + 1); } + // empty the fields + $("#multimedia_name").val(''); + $("#multimedia_url").val(''); + $("#media_type_image").prop('checked', ''); + $("#media_type_other").prop('checked', ''); $("#multimedia_form").dialog("close"); $(".remove-media").click(function(){ $(this).parents('li').remove(); diff --git a/chimere/templates/chimere/blocks/categories.html b/chimere/templates/chimere/blocks/categories.html index 8c8a8f8..c273ae4 100644 --- a/chimere/templates/chimere/blocks/categories.html +++ b/chimere/templates/chimere/blocks/categories.html @@ -1,14 +1,14 @@ {% load i18n %} <ul id='ul_categories'> {% for category, lst_sub_categories in sub_categories %} - <li> + <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}}'> + <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}}'/> diff --git a/chimere/templates/chimere/blocks/footer.html b/chimere/templates/chimere/blocks/footer.html index f2961c3..d895f88 100644 --- a/chimere/templates/chimere/blocks/footer.html +++ b/chimere/templates/chimere/blocks/footer.html @@ -1,3 +1,3 @@ {% load i18n %} -{% trans "This site uses Chimère"%} - <img src="{{STATIC_URL}}chimere/img/copyleft.png" alt="copyleft"/> 2008-2012 <a href='http://blog.peacefrogs.net/nim/chimere/'>Chimère project</a> - {% trans "Map"%} <img src="{{STATIC_URL}}chimere/img/copyleft.png" alt="copyleft"/> <a href='http://openstreetmap.org/'>OpenStreetMap</a> +{% trans "This site uses Chimère"%} - <img src="{{STATIC_URL}}chimere/img/copyleft.png" alt="copyleft"/> 2008-2013 <a href='http://blog.peacefrogs.net/nim/chimere/'>Chimère project</a> - {% trans "Map"%} <img src="{{STATIC_URL}}chimere/img/copyleft.png" alt="copyleft"/> <a href='http://openstreetmap.org/'>OpenStreetMap</a> diff --git a/chimere/templates/chimere/blocks/head_chimere.html b/chimere/templates/chimere/blocks/head_chimere.html index 4031ac4..147d05b 100644 --- a/chimere/templates/chimere/blocks/head_chimere.html +++ b/chimere/templates/chimere/blocks/head_chimere.html @@ -1,16 +1,18 @@ {% for css_url in OSM_CSS_URLS %} <link rel="stylesheet" href="{{ css_url }}" />{% endfor %} {% for js_url in OSM_JS_URLS %} -<script src="{{ js_url }}"></script>{% endfor %} -<script src="{{ STATIC_URL }}chimere/js/jquery.chimere.js"></script> +<script src="{{ js_url }}" type="text/javascript"></script>{% endfor %} +{% if routing %}<script src="{{ STATIC_URL }}chimere/js/routing-widget.js" type="text/javascript"></script>{% endif %} +<script src="{{ STATIC_URL }}chimere/js/clustering.js" type="text/javascript"></script> +<script src="{{ STATIC_URL }}chimere/js/jquery.chimere.js" type="text/javascript"></script> <script type="text/javascript"> /* Global variables */ var STATIC_URL = static_url = "{{ STATIC_URL }}"; var MEDIA_URL = media_path = "{{ MEDIA_URL }}"; var extra_url = "{{ EXTRA_URL }}"; </script> -<script src="{{ STATIC_URL }}chimere/js/utils.js"></script> -<script src="{{ STATIC_URL }}chimere/js/base.js"></script> +<script src="{{ STATIC_URL }}chimere/js/utils.js" type="text/javascript"></script> +<script src="{{ STATIC_URL }}chimere/js/base.js" type="text/javascript"></script> <script type="text/javascript"> var DEFAULT_ZOOM = {{ DEFAULT_ZOOM }}; var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:{{ EPSG_DISPLAY_PROJECTION }}'); @@ -23,8 +25,9 @@ var area_name = '{{ area_name }}';{% endif %} $(function() {$( ".draggable" ).draggable({handle:"h2"});}); + var get_share_url = '{% url chimere:get-share-url %}'; </script> -<style> +<style type="text/css"> .olControlPanPanel div { background-image: url({{STATIC_URL}}chimere/img/pan-panel.png); } diff --git a/chimere/templates/chimere/blocks/head_form.html b/chimere/templates/chimere/blocks/head_form.html new file mode 100644 index 0000000..032a711 --- /dev/null +++ b/chimere/templates/chimere/blocks/head_form.html @@ -0,0 +1,2 @@ + +<script src="{{ TINYMCE_URL }}tiny_mce.js" type="text/javascript"></script> diff --git a/chimere/templates/chimere/blocks/head_jme.html b/chimere/templates/chimere/blocks/head_jme.html index a3fe683..bf31e6f 100644 --- a/chimere/templates/chimere/blocks/head_jme.html +++ b/chimere/templates/chimere/blocks/head_jme.html @@ -1,16 +1,16 @@ <script class="jwPlayer" type="application/swf" src="{{STATIC_URL}}jme/packages/player.swf"></script> -<script src="{{STATIC_URL}}jme/packages/mm.full.min.js"></script> -<script src="{{STATIC_URL}}jme/utils/jmeEmbedControls.js"></script> +<script src="{{STATIC_URL}}jme/packages/mm.full.min.js" type="text/javascript"></script> +<script src="{{STATIC_URL}}jme/utils/jmeEmbedControls.js" type="text/javascript"></script> <link rel="stylesheet" href="{{STATIC_URL}}jme/css/player-controls.css" /> <!-- a11y-slider --> -<script src="{{STATIC_URL}}jme/utils/a11y-slider.ext.js"></script> +<script src="{{STATIC_URL}}jme/utils/a11y-slider.ext.js" type="text/javascript"></script> <!-- workaround for flash bug in ie --> -<script src="{{STATIC_URL}}jme/utils/reinitjme.js"></script> +<script src="{{STATIC_URL}}jme/utils/reinitjme.js" type="text/javascript"></script> <!-- fullwindow plugin --> <script class="jme-jwPlayer" type="application/swf" src="{{STATIC_URL}}jme/packages/jmefs.swf"></script> -<script src="{{STATIC_URL}}jme/plugins/fullwindow.js"></script> +<script src="{{STATIC_URL}}jme/plugins/fullwindow.js" type="text/javascript"></script> <!-- useractivity --> -<script src="{{STATIC_URL}}jme/utils/useractivity.js"></script> +<script src="{{STATIC_URL}}jme/utils/useractivity.js" type="text/javascript"></script> <!-- prettyPhoto not jme but media --> <link rel="stylesheet" href="{{STATIC_URL}}prettyPhoto/css/prettyPhoto.css" /> diff --git a/chimere/templates/chimere/blocks/live_coordinates.html b/chimere/templates/chimere/blocks/live_coordinates.html index eb6c4c3..0199630 100644 --- a/chimere/templates/chimere/blocks/live_coordinates.html +++ b/chimere/templates/chimere/blocks/live_coordinates.html @@ -1,4 +1,6 @@ <script type='text/javascript'> + var resolutions; + var zoomOffset; OpenLayers.ImgPath = '%schimere/img/'; var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:%s'); var EPSG_PROJECTION = epsg_projection = new OpenLayers.Projection('EPSG:%s'); diff --git a/chimere/templates/chimere/blocks/map.html b/chimere/templates/chimere/blocks/map.html index 9788528..e00ff8b 100644 --- a/chimere/templates/chimere/blocks/map.html +++ b/chimere/templates/chimere/blocks/map.html @@ -5,18 +5,25 @@ </script> <div id="waiting"> <div id="waiting-content"> - <img src='{{STATIC_URL}}chimere/img/ajax-loader.gif'/> + <img alt='Ajax loader' src='{{STATIC_URL}}chimere/img/ajax-loader.gif'/> <p>{% trans "Loading of the map in progress" %}</p> </div> </div> +<div id="layer_selection"> + <h4>{% trans "Display options" %}</h4> + <ul id='layer_list'> + <li class='head layer_map_type'>{% trans "Map type"%}</li> + </ul> +</div> <script type="text/javascript"> {% if single_category %} $(function() {$('#panel').hide()});{% endif %} var chimere_init_options = {}; chimere_init_options["default_icon"] = '{{STATIC_URL}}img/marker-green.png'; - chimere_init_options["map_layers"] = [{{map_layers|safe|escape}}]; + chimere_init_options["map_layers"] = [{{js_map_layers|safe|escape}}]; chimere_init_options['permalink_label'] = '{%trans "Permalink"%}'; chimere_init_options['permalink_element'] = document.getElementById('permalink'); + chimere_init_options['routing'] = {{routing}}; {% if dynamic_categories %}chimere_init_options['dynamic_categories'] = true;{% endif %} {% if default_area %} chimere_init_options["default_area"] = new Array({{default_area.upper_left_corner.x}}, {{default_area.upper_left_corner.y}}, {{default_area.lower_right_corner.x}}, {{default_area.lower_right_corner.y}}); @@ -24,11 +31,16 @@ {% if p_zoom %}chimere_init_options["zoom"] = {{ p_zoom }};{% endif %} {% if p_lat %}chimere_init_options["lat"] = {{ p_lat }};{% endif %} {% if p_lon %}chimere_init_options["lon"] = {{ p_lon }};{% endif %} + {% if p_routing_start_lon %}chimere_init_options["routing_start_lon"] = {{ p_routing_start_lon }};{% endif %} + {% if p_routing_start_lat %}chimere_init_options["routing_start_lat"] = {{ p_routing_start_lat }};{% endif %} + {% if p_routing_end_lon %}chimere_init_options["routing_end_lon"] = {{ p_routing_end_lon }};{% endif %} + {% if p_routing_end_lat %}chimere_init_options["routing_end_lat"] = {{ p_routing_end_lat }};{% endif %} + {% if p_routing_steps %}chimere_init_options["routing_steps_lonlat"] = [{{ p_routing_steps }}];{% endif %} chimere_init_options["icon_offset"] = new OpenLayers.Pixel({{icon_offset_x}}, {{icon_offset_y}}); chimere_init_options["dynamic_categories"] = {{ dynamic_categories }}; {% if p_display_submited %}chimere_init_options["display_submited"] = {{ p_display_submited }};{% endif %} - chimere_init_options["checked_categories"] = {{ p_checked_categories }}; + chimere_init_options["checked_categories"] = [{% for cc in checked_categories %}{% if forloop.counter0 > 0 %}, {% endif %}{{cc}}{% endfor %}]; {% if area_id %}chimere_init_options['area_id'] = "{{area_id}}";{% endif %} {% if p_current_feature %} chimere_init_options["display_feature"] = {{ p_current_feature }};{% endif %} @@ -44,5 +56,28 @@ {% if zoom %} $('#maps').chimere('zoom', {'area':{{zoom}} }); {% endif %} -</script> + // init layer selection + $(function() { + {% for layer_name, js, def in map_layers %} + $('#layer_list').append("<li><input type='radio' value='{{forloop.counter0}}' name='layer_type' id='layer_{{forloop.counter}}'{% if def %} checked='checked'{% endif %}><label for='layer_{{forloop.counter}}'>{{layer_name}}</li>");{% endfor %} + {% for subcat in subcat_layer %} + {% if not subcat.category %} + $('#layer_list').append("<li class='head layer_category'>{{subcat.name}}</li>");{% else %} + $('#layer_list').append("<li><input type='checkbox' name='layer_cat' value='category_{{subcat.pk}}' id='layer_cat_{{subcat.pk}}'{% if subcat.pk in checked_categories %} checked='checked'{% endif %}><label for='layer_cat_{{subcat.pk}}'>{{subcat.name}}</li>");{%endif%}{% endfor %} + $('#layer_selection h4').click(function(){ + $('#layer_list').toggle(); + }); + $('#layer_list input[name=layer_type]').change(function(){ + $('#{{map_id}}').chimere('changeMapLayer', $(this).val()); + }); + $('#layer_list input[name=layer_cat]').change(function(){ + // the prop has to be called twice not to mess up with the triggered + // click + $('#'+$(this).val()).prop("checked", this.checked); + $('#'+$(this).val()).trigger('click'); + $('#'+$(this).val()).prop("checked", this.checked); + }); + }); +</script> +<div id='marker_hover'><div id='marker_hover_content'></div></div> diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html new file mode 100644 index 0000000..38fb4a8 --- /dev/null +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -0,0 +1,14 @@ +{% load i18n %} +<div id='chimere_map_menu'> + <ul> + {% if routing %} + <li id='map_menu_from' class='routing_item'>{% trans "From" context "routing" %}</li> + <li id='map_menu_step' class='routing_item'>{% trans "Add a step" context "routing" %}</li> + <li id='map_menu_to' class='routing_item'>{% trans "To" context "routing" %}</li> + <li id='map_menu_clear' class='routing_item'>{% trans "Clear the itinerary" context "routing" %}</li> + {% endif%} + <li id='map_menu_zoomin'>{% trans "Zoom in" %}</li> + <li id='map_menu_zoomout'>{% trans "Zoom out" %}</li> + <li id='map_menu_center'>{% trans "Center the map here" %}</li> + </ul> +</div> diff --git a/chimere/templates/chimere/blocks/multimedia_file.html b/chimere/templates/chimere/blocks/multimedia_file.html index cc7c5d3..a360a9e 100644 --- a/chimere/templates/chimere/blocks/multimedia_file.html +++ b/chimere/templates/chimere/blocks/multimedia_file.html @@ -1,6 +1,6 @@ {% load i18n %} {% if multimedia_item.picture %} -<a rel="prettyPhoto" href='{{multimedia_item.picture.url}}' ><img class='media-img' alt="{{multimedia_item.name}}" src='{{multimedia_item.thumbnailfile.url}}'/></a>{% endif %} +<a rel="prettyPhoto" href='{{multimedia_item.picture.url}}' ><img class='media-img thumbnail' alt="{{multimedia_item.name}}" src='{{multimedia_item.thumbnailfile.url}}'/></a>{% endif %} {% if multimedia_item.url %} {% if multimedia_item.multimedia_type.iframe %} diff --git a/chimere/templates/chimere/blocks/news.html b/chimere/templates/chimere/blocks/news.html new file mode 100644 index 0000000..fa581f7 --- /dev/null +++ b/chimere/templates/chimere/blocks/news.html @@ -0,0 +1,53 @@ +{% load i18n sanitize chimere_tags %} +{% if news_lst %} +<a href='#' id='news_button' class='ui-widget ui-button ui-state-default ui-corner-all'>{% trans "News"%}</a> +<script type='text/javascript'> +function display_news(){$("#welcome").dialog({title:"{% trans "News"%}", + width:360});} +$("#news_button").bind('click', display_welcome); +$(function(){ + $('#news div.media-player').jmeEmbedControls(); + $('#news video').each(function(index){$(this).pause()}); + $('#news audio').each(function(index){$(this).pause()}); + {% if display %}display_news();{%endif%} +}); +</script> +<div id='news' style='display:none'> + <div id='detail_content'> + <div class='news'> + {% if news_lst %} + {% for news in news_lst %} + <div class='info'> + {% if news.title %} + <h3>{{news.title}} – {{ news.date }}</h3> + <p>{{news.content|safe}}</p> + {% else %} + <h3>{{news.name}} – {{ news.start_date }}{% if news.end_date %} - {{ news.end_date }}{% endif %}</h3> + {% if news.default_pictures or news.default_pictures or news.default_multimedia_items%} + <div class='small-gallery'> + {% for picture in news.default_pictures %} + {% multimedia_render picture %} + {%endfor%} + {% for multimedia_item in news.default_multimedia_items %} + {% multimedia_render multimedia_item %} + {%endfor%} + </div> + {%endif%} + {% if news.description %} + <p class='description'>{{news.description|sanitize:"p b i br hr strong em span:style a:href:target ul li ol h1 h2 h3 h4 table td th tr"|safe}}</p> + {% endif %} + {% for property in news.getProperties %} + <p class='{{news.propertymodel.getNamedId}}'>{{ property.value|sanitize:"p b i br hr strong em span:style a:href:target ul li ol h1 h2 h3 h4 table td th tr"|safe }}</p> + {% endfor %} + <p class='marker_link'><a href='{% get_tinyfied_url news area_name %}'>{% trans "See it on the map"%}</a></p> + {% endif %} + </div> + {%endfor%} + {% endif %} + <div class='info'> + </div> + </div> + </div> +</div> +{% endif %} + diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html new file mode 100644 index 0000000..db97191 --- /dev/null +++ b/chimere/templates/chimere/blocks/routing.html @@ -0,0 +1,48 @@ +{% load i18n %} +{# Don't forget to include routing-widget.js in your main template #} +{% if routing %} +{{itinerary_form.media}} +<a href='#' id='routing_button' class='ui-widget ui-button ui-state-default ui-corner-all'>{% trans "Itinerary"%}</a> +<div id='chimere_itinerary_panel'> + <div id='chimere_itinerary_form'> + {% for hidden in itinerary_form.hidden_fields %} + {{ hidden }} + {% endfor %} + {% for field in itinerary_form.visible_fields %} + <div id='{{field.auto_id}}_div'> + {% if field.label %}<label for='{{field.auto_id}}'>{{ field.label }}</label>{%endif%} + {{field}}</div> + {% endfor %} + <a id='add_step_link' href='#'>{% trans "Add a step" %}</a> + <span id='search_routing'>{% trans "Search" %}</span> + </div> + <div id='chimere_itinerary'> + <div id='chimere_itinerary_action'> + <ul class='action'> + <li class='ui-widget ui-button ui-state-default ui-corner-all'> + <a href='#' id='chimere_itinerary_modify'>{% trans "Modify" %}</a> + </li> + <li class='ui-widget ui-button ui-state-default ui-corner-all'> + <a href='#' id='chimere_itinerary_new'>{% trans "New search" %}</a> + </li> + </ul> + </div> + <div class='itinerary_label' id='total_label_div'> + <span id='chimere_total_label'></span> + </div> + <div class='itinerary_label'> + <span class='label'>{% trans "Start:"%}</span> <span id='chimere_start_label'></span></div> + <div id='chimere_itinerary_content'> + </div> + <div class='itinerary_label'> + <span class='label'>{% trans "Finish:"%}</span> <span id='chimere_end_label'></span> + </div> + </div> +</div> +<script language='javascript' type='text/javascript'> +<!-- +var step_label = "{% trans "Step" %}"; +var routing_fail_message = "{{routing_fail_message|safe}}"; +// --> +</script> +{% endif%} diff --git a/chimere/templates/chimere/blocks/share_bar.html b/chimere/templates/chimere/blocks/share_bar.html new file mode 100644 index 0000000..e421a0f --- /dev/null +++ b/chimere/templates/chimere/blocks/share_bar.html @@ -0,0 +1,39 @@ +{% load i18n %} + {% if share_networks %} + {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %} + <a href='{{share_network.1}}'>{{share_network.0}}</a> + {% endfor %}{%else%} + <ul class='share'> + <li>{% trans "Share"%}</li>{% for share_network in share_networks %} + <li><a class='share_link share_id_{{share_network.0}}' href='{{share_network.1}}'><img src="{{share_network.2}}" alt="{{share_network.0}}"/></a></li> + {% endfor %}</ul>{% endif %} + <script language='text/javascript'> + $(function(){ + $('.share_link').click(function(){ + var href = $(this).attr('href'); + var url = '{% url chimere:get-share-url %}'; + var classes = $(this).attr('class').split(' '); + prefix = 'share_id_'; + var share_id; + for (idx=0;idx<classes.length;idx++){ + if(classes[idx].substring(0, prefix.length) == prefix){ + var share_id = classes[idx].substring(prefix.length); + } + } + var params = $('#permalink a').attr('href').split('/'); + url += share_id + params[params.length-1]; + $.ajax({url: url, + dataType: "html", + success: function (url) { + window.open(url); + return false; + }, + error: function(){ + return false; + } + }); + return false; + }); + }); + </script> + {% endif %} diff --git a/chimere/templates/chimere/default_extra_page.html b/chimere/templates/chimere/default_extra_page.html new file mode 100644 index 0000000..884d4cc --- /dev/null +++ b/chimere/templates/chimere/default_extra_page.html @@ -0,0 +1,15 @@ +{% extends "chimere/base.html" %} +{% load i18n chimere_tags %} +{% block extra_head %} + {{ block.super }} + {{ form.media }} + {% head_jquery %} +{% endblock %} +{% block message_map %}{% endblock %} +{% block message_edit%}{% endblock %} +{% block content %} + {{ block.super }} + <h3>{{title}}</h3> + {{content|safe}} +{% endblock %} + diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html index eec932c..ed0ea5c 100644 --- a/chimere/templates/chimere/detail.html +++ b/chimere/templates/chimere/detail.html @@ -34,18 +34,8 @@ {% if moderator_emails %} <a href="mailto:?from={{moderator_emails}}&subject={% trans "Propose amendment" %}&body={% trans "I would like to propose an amendment for this item:"%} {{share_url}}"> {% trans "Propose amendment" %} - </a>{%endif%}</p> - {% if share_networks %} - <p class='detail_share'> - {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %} - <a href='{{share_network.1}}'>{{share_network.0}}</a> - {% endfor %}{%else%} - <ul class='share'> - <li>{% trans "Share"%}</li>{% for share_network in share_networks %} - <li><a href='{{share_network.1}}'><img src="{{share_network.2}}" alt="{{share_network.0}}"/></a></li> - {% endfor %}</ul>{% endif %} - </p> -{% endif %} + </a>{%endif%} + {% share_bar marker.name %} </div> {% if marker.multimedia_items %} <div id='gallery-{{time_now}}' class='gallery'> diff --git a/chimere/templates/chimere/edit.html b/chimere/templates/chimere/edit.html index 341f9b5..f9706d3 100644 --- a/chimere/templates/chimere/edit.html +++ b/chimere/templates/chimere/edit.html @@ -133,14 +133,15 @@ </div> <div id='upload_in_progress'> <p>{% trans "Upload in progress. Please wait..." %}</p> - <p><img src='{{STATIC_URL}}chimere/img/ajax-loader.gif'/></p> + <p><img alt='Ajax loader' src='{{STATIC_URL}}chimere/img/ajax-loader.gif'/></p> </div> <script text='text/javascript'> $( "#upload_in_progress" ).dialog({ modal: true, resizable:false, height:110, - autoOpen:false + autoOpen:false, + dialogClass:'alert-box' } ); $(".ui-dialog-titlebar").hide(); diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index 76f796d..b7aa868 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -4,7 +4,7 @@ {% head_jquery %} {% head_chimere %} {% head_jme %} -<script src="{{ STATIC_URL }}chimere/js/jquery.chimere.js"></script> +<script src="{{ STATIC_URL }}chimere/js/jquery.chimere.js" type="text/javascript"></script> {{ block.super }} {% endblock %} {% block message_edit %}{% endblock %} @@ -18,20 +18,36 @@ </form> </div> + <div id='category_description'> + </div> + <script type='text/javascript'> + $(function(){$('#category_description').dialog({'autoOpen':false});}); + </script> + <div id='utils-div' class='ui-widget ui-state-default ui-corner-all'> {% if areas_visible %} {% display_areas %} {% endif %} + {% routing %} + {% 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> - <div id='category_detail'></div> {% endblock %} {% block content %} {{block.super}} + <div id='main-map'></div> +<script type="text/javascript"> + $("#main-map").show(); +</script> + {% map_menu %} {% map 'main-map' %} + <div id='chimere_message'></div> + <script type='text/javascript'> + $(function(){$('#chimere_message').dialog({'autoOpen':false});}); + </script> {% endblock %} {% block footer %} <p class='map-footer'>{% include "chimere/blocks/footer.html" %}</p> diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index aadaa6b..a6b82c8 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -10,6 +10,8 @@ from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse from django.db.models import Q, Count +from django.template import defaultfilters +from django.utils.translation import ugettext as _ from django.template.loader import render_to_string from chimere.models import Marker, Area, News, SubCategory, MultimediaType @@ -39,22 +41,9 @@ def submited(context): return {"edit_url":reverse('chimere:edit'), "index_url":reverse('chimere:index')} -@register.inclusion_tag('chimere/blocks/welcome.html', takes_context=True) -def display_news(context, display=False): - """ - Welcome message and active news. - """ - area = None - context_data = {'display':display} - if "area_name" in context: - try: - area = Area.objects.get(urn=context["area_name"]) - context_data['area_name'] = context['area_name'] - context_data['welcome_message'] = area.welcome_message - except ObjectDoesNotExist: - pass +def get_news(area=None): # Retrieve news - news = News.objects.filter(available=True) + news = News.objects.filter(available=True, is_front_page=True) if area: news = news.filter(Q(areas__isnull=True)|Q(areas__in=[area.pk])) news = list(news.all()) @@ -62,14 +51,50 @@ def display_news(context, display=False): # Retrieve active markers today = date.today() after = today + timedelta(settings.CHIMERE_DAYS_BEFORE_EVENT) - q = Marker.objects.filter(status='A').filter(start_date__lte=after - ).filter(Q(end_date__gte=today)| + q = Marker.objects.filter(status='A').filter(start_date__lte=after, + is_front_page=True).filter(Q(end_date__gte=today)| (Q(end_date__isnull=True) & Q(start_date__gte=today))) if area: q = q.filter(area.getIncludeMarker()) news += list(q) - news.sort(key=lambda x:x.date) - context_data['news_lst'] = news + news.sort(key=lambda x:x.date, reverse=True) + return news + +@register.inclusion_tag('chimere/blocks/welcome.html', takes_context=True) +def display_welcome(context, display=False, title=''): + """ + Welcome message and active news. + """ + context_data = {'display':display} + area = None + if "area_name" in context: + try: + area = Area.objects.get(urn=context["area_name"]) + context_data['area_name'] = context['area_name'] + context_data['welcome_message'] = area.welcome_message + except ObjectDoesNotExist: + pass + context_data['news_lst'] = get_news(area)[:3] + context_data['STATIC_URL'] = settings.STATIC_URL + context_data['title'] = title if title \ + else _(u"Welcome to the %s") % settings.PROJECT_NAME + return context_data + +@register.inclusion_tag('chimere/blocks/news.html', takes_context=True) +def display_news(context, title=''): + """ + All news. + """ + area = None + context_data = {'STATIC_URL':settings.STATIC_URL} + if "area_name" in context: + try: + area = Area.objects.get(urn=context["area_name"]) + context_data['area_name'] = context['area_name'] + context_data['welcome_message'] = area.welcome_message + except ObjectDoesNotExist: + pass + context_data['news_lst'] = get_news(area) return context_data @register.inclusion_tag('chimere/blocks/head_jquery.html', takes_context=True) @@ -118,9 +143,41 @@ def head_chimere(context): "MAP_LAYER": settings.CHIMERE_DEFAULT_MAP_LAYER, "OSM_CSS_URLS": settings.OSM_CSS_URLS, "OSM_JS_URLS": settings.OSM_JS_URLS, + 'routing': settings.CHIMERE_ENABLE_ROUTING \ + if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') else False + } + return context_data + +@register.inclusion_tag('chimere/blocks/head_form.html') +def head_form(): + """ + Manualy add forms header (necessary in case of ajax load) + """ + context_data = { + "TINYMCE_URL": settings.TINYMCE_URL, } return context_data +@register.inclusion_tag('chimere/blocks/map_menu.html', takes_context=True) +def map_menu(context): + context_data = {'routing': settings.CHIMERE_ENABLE_ROUTING \ + if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') else False} + return context_data + +@register.inclusion_tag('chimere/blocks/routing.html', takes_context=True) +def routing(context): + if not hasattr(settings, 'CHIMERE_ENABLE_ROUTING') or \ + not settings.CHIMERE_ENABLE_ROUTING: + return {'routing':False} + context_data = { + 'routing':settings.CHIMERE_ENABLE_ROUTING, + 'itinerary_form':context['itinerary_form'], + 'routing_fail_message':_(settings.CHIMERE_ROUTING_FAIL_MESSAGE + ).replace('\n', '\\n'), + 'routing_transport':context['routing_transport']} + context_data['STATIC_URL'] = settings.STATIC_URL + return context_data + @register.inclusion_tag('chimere/blocks/map.html', takes_context=True) def map(context, map_id='map'): context_data = {'map_id':map_id, @@ -129,12 +186,18 @@ def map(context, map_id='map'): context_data['icon_offset_y'] = settings.CHIMERE_ICON_OFFSET_Y context_data['icon_width'] = settings.CHIMERE_ICON_WIDTH context_data['icon_height'] = settings.CHIMERE_ICON_HEIGHT + context_data['routing'] = 'true' \ + if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') and \ + settings.CHIMERE_ENABLE_ROUTING \ + else 'false' area_name = context['area_name'] if 'area_name' in context else 'area_name' map_layers, default_area = get_map_layers(area_name) - context_data['map_layers'] = ", ".join(map_layers) + context_data['js_map_layers'] = ", ".join( + [js for name, js, default in map_layers]) + context_data['map_layers'] = map_layers if default_area: context_data['selected_map_layer'] = default_area - context_data['p_checked_categories'] = None + context_data['checked_categories'] = [] area = None if area_name: try: @@ -146,7 +209,10 @@ def map(context, map_id='map'): area = Area.objects.get(default=True) except ObjectDoesNotExist: pass + subcat_layer = SubCategory.objects.filter(as_layer=True, available=True) if area: + if area.subcategories.count(): + subcat_layer = subcat_layer.filter(areas__pk=area.pk) context_data['area_id'] = area_name if 'zoomout' in context and context['zoomout']: context_data['zoom'] = "[%s]" % ",".join(( @@ -156,11 +222,10 @@ def map(context, map_id='map'): unicode(area.lower_right_corner.y))) if area.subcategories.filter(available=True).count() == 1: context_data['single_category'] = True - context_data['p_checked_categories'] = "[%d]" % \ - area.subcategories.all()[0].pk + context_data['checked_categories'] = area.subcategories.all()[0].pk elif area.default_subcategories.count(): - context_data['p_checked_categories'] = unicode([subcategory.pk - for subcategory in area.default_subcategories.all()]) + context_data['checked_categories'] = [s.pk + for s in area.default_subcategories.all()] if area.restrict_to_extent: context_data['restricted_extent'] = """ var bounds = new OpenLayers.Bounds(); @@ -168,17 +233,20 @@ bounds.extend(new OpenLayers.LonLat(%f, %f)); bounds.extend(new OpenLayers.LonLat(%f, %f)); """ % (area.upper_left_corner.x, area.upper_left_corner.y, area.lower_right_corner.x, area.lower_right_corner.y) - + context_data['subcat_layer'], c_cat = [], None + for subcat in subcat_layer.order_by('category__order', 'category').all(): + if subcat.category != c_cat: + context_data['subcat_layer'].append(subcat.category) + c_cat = subcat.category + context_data['subcat_layer'].append(subcat) if SubCategory.objects.filter(available=True).count() <= 1: context_data['single_category'] = True - if not context_data['p_checked_categories']: + if not context_data['checked_categories']: cat = '' if SubCategory.objects.filter(available=True).count(): cat = unicode(SubCategory.objects.filter(available=True ).all()[0].pk) - context_data['p_checked_categories'] = "[%s]" % cat - if not context_data['p_checked_categories']: - context_data['p_checked_categories'] = "[]" + context_data['checked_categories'] = cat context_data['dynamic_categories'] = 'true' \ if area and area.dynamic_categories else 'false' if 'request' not in context: @@ -188,7 +256,8 @@ bounds.extend(new OpenLayers.LonLat(%f, %f)); context_data['p_current_route'] = context.get('current_route') if request.GET: for key in ('zoom', 'lon', 'lat', 'display_submited', - 'current_feature'): + 'current_feature', 'routing_start_lon', 'routing_start_lat', + 'routing_end_lon', 'routing_end_lat', 'routing_steps'): if key in request.GET and request.GET[key]: context_data['p_'+key] = request.GET[key] else: @@ -196,7 +265,7 @@ bounds.extend(new OpenLayers.LonLat(%f, %f)); if 'checked_categories' in request.GET \ and request.GET['checked_categories']: cats = request.GET['checked_categories'].split('_') - context_data['p_checked_categories'] = "[%s]" % ",".join(cats) + context_data['checked_categories'] = cats return context_data @register.inclusion_tag('chimere/blocks/multimedia_file.html', @@ -218,6 +287,16 @@ def get_tinyfied_url(marker, area_name=''): url = marker.get_absolute_url(area_name) return url +@register.inclusion_tag('chimere/blocks/share_bar.html', + takes_context=True) +def share_bar(context, name='', email_only=False): + context['STATIC_URL'] = settings.STATIC_URL + context['name'] = name + context['email_only'] = email_only + context['share_networks'] = [(defaultfilters.slugify(name), url, icon) + for name, url, icon in settings.CHIMERE_SHARE_NETWORKS] + return context + @register.filter(name='ol_map') def ol_map(item, arg='map_id'): geom, geom_type = None, None diff --git a/chimere/tests.py b/chimere/tests.py index 54c1acd..fb48205 100644 --- a/chimere/tests.py +++ b/chimere/tests.py @@ -4,6 +4,7 @@ import datetime import lxml.etree import os +import simplejson as json test_path = os.path.abspath(__file__) test_dir_path = os.path.dirname(test_path) + os.sep @@ -90,12 +91,14 @@ def marker_setup(sub_categories=[]): markers.append(marker_1) marker_2 = Marker.objects.create(name="Marker 2", status='A', point='SRID=4326;POINT(-3.5 48.4)', + is_front_page=True, available_date=current_date, start_date=current_date) marker_2.categories.add(sub_categories[1]) markers.append(marker_2) marker_3 = Marker.objects.create(name="Marker 3", status='A', point='SRID=4326;POINT(-4.5 48.45)', + is_front_page=True, available_date=current_date - datetime.timedelta(days=60), start_date=current_date - datetime.timedelta(days=60), end_date=current_date - datetime.timedelta(days=30)) @@ -259,8 +262,14 @@ class OSMImporterTest(TestCase, ImporterTest): importer2 = Importer.objects.create(importer_type='OSM', source=test_dir_path+'tests/sample_ways.osm') importer2.categories.add(subcategories[1]) + importer3 = Importer.objects.create(importer_type='OSM', + source='http://open.mapquestapi.com/xapi/api/0.6/way'\ + '[highway=motorway]'\ + '[bbox=2.0393839939136975,48.68908639634696,'\ + '2.3140421970277316,48.790972349390415]') - self.marker_importers = [(importer1, 19), (importer2, 8)] + self.marker_importers = [(importer1, 19), (importer2, 8), + (importer3, None)] class GeoRSSImporterTest(TestCase, ImporterTest): def setUp(self): @@ -400,6 +409,13 @@ class DynamicCategoryTest(TestCase): 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') + response = self.client.get(url) + self.assertEqual(200, response.status_code) + cats = json.loads(response.content)['categories'] + self.assertEqual(len(cats), 2) + class NewsTest(TestCase): def setUp(self): self.areas = areas_setup() @@ -411,10 +427,10 @@ class NewsTest(TestCase): start_date=current_date - datetime.timedelta(days=90), end_date=None) self.news = [] - self.news.append(News.objects.create(title=u"Test news 1", - available=True)) - self.news.append(News.objects.create(title=u"Test news 2", - available=False)) + self.news.append(News.objects.create(is_front_page=True, + title=u"Test news 1", available=True)) + self.news.append(News.objects.create(is_front_page=True, + title=u"Test news 2", available=False)) def test_news_display(self): context = display_news(Context({})) diff --git a/chimere/urls.py b/chimere/urls.py index 9d4018a..164ef68 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -20,6 +20,7 @@ from django.conf import settings from django.conf.urls.defaults import * from django.contrib import admin +from django.core.exceptions import ImproperlyConfigured admin.autodiscover() from chimere.models import Area @@ -51,9 +52,26 @@ if settings.CHIMERE_FEEDS: LatestPOIsByZoneID(), name='feeds-areaid'), ) +if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') \ + and settings.CHIMERE_ENABLE_ROUTING: + if not hasattr(settings, 'CHIMERE_ROUTING_TRANSPORT') \ + or not settings.CHIMERE_ROUTING_TRANSPORT: + raise ImproperlyConfigured(u"CHIMERE_ROUTING_TRANSPORT must be set in"\ + u" settings if you enable routing") + urlpatterns += patterns('chimere.views', + url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?route/'\ + r'(?P<transport>(%s))/((?P<speed>[0-9][0-9]*)/)?' + r'(?P<lon1>[-]?[0-9]+[.]?[0-9]*)_(?P<lat1>[-]?[0-9]+[.]?[0-9]*)_'\ + r'(?P<lonlat_steps>([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ + r'(?P<lon2>[-]?[0-9]+[.]?[0-9]*)_(?P<lat2>[-]?[0-9]+[.]?[0-9]*)$' % + ('|'.join([key for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])), + 'route', name="route"), + ) + urlpatterns += patterns('chimere.views', url(r'^charte/?$', 'charte', name="charte"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', name="contact"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', + name="contact"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/$', 'edit', name="edit"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/(?P<item_id>\w+)/(?P<submited>\w+)?$', @@ -71,12 +89,20 @@ urlpatterns += patterns('chimere.views', name="getgeoobjects"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAvailableCategories/$', 'get_available_categories', name="get_categories"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAllCategories/$', + 'get_all_categories', name="get_all_categories"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getCategory/(?P<category_id>\d+)/?$', + 'getCategory', name="get_category"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?get-share-url/(?P<network>\w+)?$', + 'getShareUrl', name="get-share-url"), url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?ty/(?P<tiny_urn>\w+)$', 'redirectFromTinyURN', name="tiny"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?upload_file/((?P<category_id>\w+)/)?$', 'uploadFile', name='upload_file'), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?process_route_file/(?P<file_id>\d+)/$', 'processRouteFile', name='process_route_file'), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?dyn/(?P<page_id>\w+)/$', + 'extraPage', name='extra_page'), # At the end, because it catches large url(r'^(?P<area_name>[a-zA-Z0-9_-]+)?', 'index', name="index"), ) diff --git a/chimere/utils.py b/chimere/utils.py index b383eb0..f5379aa 100644 --- a/chimere/utils.py +++ b/chimere/utils.py @@ -86,6 +86,7 @@ class ImportManager(object): 'import_key__icontains':'%s:%s;' % (key, import_key), 'import_source':self.importer_instance.source} try: + item = None if pk: ref_item = cls.objects.get(pk=pk) else: @@ -505,10 +506,10 @@ class CSVManager(ImportManager): return (0, 0, msg) reader = csv.reader(source, delimiter=';', quotechar='"') prop_cols = [] - for pm in Marker.properties(): + for pm in Marker.all_properties(): prop_cols.append((pm.name, pm.getAttrName(), pm.getAttrName()+'_set')) - cols = self.COLS + prop_cols + cols = list(self.COLS) + prop_cols datas = [] for idx, row in enumerate(reader): if not idx: # first row @@ -538,7 +539,7 @@ class CSVManager(ImportManager): dct['route'] = geom else: continue - import_key = pk if pk else name + import_key = pk if pk else name.decode('utf-8') item, updated, created = self.create_or_update_item(cls, dct, import_key, pk=pk) if updated: @@ -556,8 +557,8 @@ class CSVManager(ImportManager): def export(cls, queryset): dct = {'description':unicode(datetime.date.today()), 'data':[]} cls_name = queryset.model.__name__.lower() - cols = cls.COLS - for pm in queryset.model.properties(): + cols = list(cls.COLS) + for pm in queryset.model.all_properties(): cols.append((pm.name, pm.getAttrName(), pm.getAttrName()+'_set')) header = [col[0] for col in cols] dct['data'].append(header) diff --git a/chimere/views.py b/chimere/views.py index 22bd50a..7c02216 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -29,27 +29,32 @@ from itertools import groupby import re from django.conf import settings +from django.contrib.gis.geos import GEOSGeometry +from django.contrib.gis.gdal.error import OGRException +from django.contrib.gis.measure import D from django.core import serializers from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse from django.db.models import Q from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import redirect, render_to_response -from django.template import loader, RequestContext -from django.utils import simplejson +from django.template import loader, RequestContext, defaultfilters +from django.utils import simplejson as json from django.utils.http import urlquote from django.utils.translation import ugettext as _ from chimere.actions import actions -from chimere.models import Category, SubCategory, PropertyModel, \ - Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile, \ - get_users_by_area +from chimere.models import Category, SubCategory, PropertyModel, Page,\ + Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile,\ + AggregatedRoute from chimere.widgets import getMapJS, PointChooserWidget, \ RouteChooserWidget, AreaWidget from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \ FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\ - notifyStaff, AreaForm + notifyStaff, AreaForm, RoutingForm, getStaffEmails + +from chimere.route import router def get_base_uri(request): base_uri = 'http://' @@ -101,9 +106,36 @@ def get_base_response(area_name=""): if area and area.dynamic_categories else False base_response_dct['JQUERY_JS_URLS'] = settings.JQUERY_JS_URLS base_response_dct['JQUERY_CSS_URLS'] = settings.JQUERY_CSS_URLS + base_response_dct['PROJECT_NAME'] = settings.PROJECT_NAME return base_response_dct, None -def index(request, area_name=None, default_area=None, simple=False): +def getShareUrl(request, area_name='', network=''): + """ + Get a share url + """ + data = getTinyfiedUrl(request, request.GET.urlencode(), area_name) + for name, url, img in settings.CHIMERE_SHARE_NETWORKS: + if defaultfilters.slugify(name) == network: + return HttpResponse(url % {'text':data['text'], 'url':data['url']}) + return HttpResponse('') + +def getShareNetwork(request, area_name='', marker=None): + """ + Get URLs to share items + """ + parameters = "" + if marker: + parameters = u'current_feature=%d' % marker.pk + parameters += u"&checked_categories=%s" % "_".join([str(m.id) \ + for m in marker.categories.all()]) + net_dct = getTinyfiedUrl(request, parameters, area_name) + share_networks = [] + for network in settings.CHIMERE_SHARE_NETWORKS: + share_networks.append((network[0], network[1] % net_dct, network[2])) + return share_networks, net_dct + +def index(request, area_name=None, default_area=None, simple=False, + get_response=False): """ Main page """ @@ -123,6 +155,10 @@ def index(request, area_name=None, default_area=None, simple=False): if request.GET and 'lat' in request.GET \ and 'lon' in request.GET: zoomout = None + if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') and \ + settings.CHIMERE_ENABLE_ROUTING: + response_dct['itinerary_form'] = RoutingForm() + response_dct['routing_transport'] = settings.CHIMERE_ROUTING_TRANSPORT if request.GET and 'current_feature' in request.GET: try: m = Marker.objects.get(pk=request.GET['current_feature']) @@ -131,18 +167,26 @@ def index(request, area_name=None, default_area=None, simple=False): except: pass response_dct.update({ - 'actions':actions, 'action_selected':('view',), + 'actions':actions(response_dct['area_name']), + 'action_selected':('view',), 'error_message':'', 'news_visible': news_visible, 'areas_visible': settings.CHIMERE_DISPLAY_AREAS, 'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER, 'dynamic_categories':response_dct['dynamic_categories'], + 'zoomout':zoomout, 'has_default_area':Area.objects.filter(default=True).count(), 'zoomout':zoomout }) + if hasattr(settings, 'CONTACT_EMAIL') and settings.CONTACT_EMAIL: + response_dct['contact_email'] = settings.CONTACT_EMAIL + response_dct['share_networks'], net_dct = \ + getShareNetwork(request, response_dct['area_name']) tpl = 'chimere/main_map.html' if simple: tpl = 'chimere/main_map_simple.html' + if get_response: + return tpl, response_dct return render_to_response(tpl, response_dct, context_instance=RequestContext(request)) @@ -278,7 +322,7 @@ def edit(request, area_name="", item_id=None, submited=False): if request.POST and request.POST.get('point'): point_value = request.POST.get('point') response_dct.update({ - 'actions':actions, + 'actions':actions(response_dct['area_name']), 'action_selected':('contribute', 'edit'), 'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER, 'form':form, @@ -357,7 +401,7 @@ def processRouteFile(request, area_name='', file_id=None): route = route_file.route if not route: return HttpResponse(status=500) - return HttpResponse('('+simplejson.dumps({'wkt':route, + return HttpResponse('(' + json.dumps({'wkt':route, 'file_id':file_id})+')', 'application/javascript', status=200) except OSError as e: @@ -386,7 +430,7 @@ def editRoute(request, area_name="", item_id=None, submited=False): if request.POST and request.POST.get('route'): route_value = request.POST.get('route') response_dct.update({ - 'actions':actions, + 'actions':actions(response_dct['area_name']), 'action_selected':('contribute', 'edit-route'), 'error_message':'', 'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER, @@ -414,7 +458,8 @@ def submited(request, area_name="", action=""): response_dct, redir = get_base_response(area_name) if redir: return redir - response_dct.update({'actions':actions, 'action_selected':action,}) + response_dct.update({'actions':actions(response_dct['area_name']), + 'action_selected':action,}) return render_to_response('chimere/submited.html', response_dct, context_instance=RequestContext(request)) @@ -425,7 +470,8 @@ def charte(request, area_name=""): response_dct, redir = get_base_response(area_name) if redir: return redir - response_dct.update({'actions':actions, 'action_selected':('charte',)}) + response_dct.update({'actions':actions(response_dct['area_name']), + 'action_selected':('charte',)}) return render_to_response('chimere/charte.html', response_dct, context_instance=RequestContext(request)) @@ -453,11 +499,32 @@ def contactus(request, area_name=""): response_dct, redir = get_base_response(area_name) if redir: return redir - response_dct.update({'actions':actions, 'action_selected':('contact',), + response_dct.update({'actions':actions(response_dct['area_name']), + 'action_selected':('contact',), 'contact_form':form, 'message':msg}) return render_to_response('chimere/contactus.html', response_dct, context_instance=RequestContext(request)) +def extraPage(request, area_name="", page_id=""): + """ + Extra dynamic pages + """ + try: + page = Page.objects.get(available=True, mnemonic=page_id) + except ObjectDoesNotExist: + return redirect(reverse('chimere:index')) + response_dct, redir = get_base_response(area_name) + if redir: + return redir + response_dct.update({'actions':actions(response_dct['area_name']), + 'action_selected':(page_id,), + 'content':page.content, + 'title':page.title}) + tpl = page.template_path if page.template_path \ + else 'chimere/default_extra_page.html' + return render_to_response(tpl, response_dct, + context_instance=RequestContext(request)) + def getDetail(request, area_name, marker_id): ''' Get the detail for a marker @@ -474,15 +541,14 @@ def getDetail(request, area_name, marker_id): if request.method == 'GET': if 'simple' in request.GET and request.GET['simple']: response_dct['simple'] = True - parameters = u'current_feature=%s' % marker_id - parameters += u"&checked_categories=%s" % "_".join([str(m.id) \ - for m in marker.categories.all()]) - net_dct = getTinyfiedUrl(request, parameters, response_dct['area_name']) - share_networks = [] + response_dct['share_networks'], net_dct = \ + getShareNetwork(request, response_dct['area_name'], marker) response_dct['share_url'] = net_dct['url'] - for network in settings.CHIMERE_SHARE_NETWORKS: - share_networks.append((network[0], network[1] % net_dct, network[2])) - response_dct['share_networks'] = share_networks + net_dct['to'] = settings.CONTACT_EMAIL + if net_dct['to']: + net_dct["body"] = _(settings.CHIMERE_MODIF_EMAIL) + response_dct['modif_by_email'] = 'mailto:?to=%(to)s&subject='\ + '%(text)s&body=%(body)s%(url)s' % net_dct # to be sure there is unique IDs during a browsing response_dct['time_now'] = datetime.datetime.now().strftime('%H%M%S') response_dct['dated'] = settings.CHIMERE_DAYS_BEFORE_EVENT \ @@ -528,17 +594,12 @@ def getGeoObjects(request, area_name, category_ids, status): status = 'A' status = status.split('_') category_ids = category_ids.split('_') - try: - q = checkDate(Q(status__in=status, categories__in=category_ids)) - query = Route.objects.filter(q) - except: - return HttpResponse('no results') - query.order_by('categories') - routes = list(query) + query = AggregatedRoute.objects.filter(status__in=status, + subcategory__in=category_ids).order_by('subcategory') jsons = [] current_cat, colors, idx = None, None, 0 - for route in routes: - c_cat = route.categories.all()[0] + for route in query.all(): + c_cat = route.subcategory if not current_cat or current_cat != c_cat: idx = 0 current_cat = c_cat @@ -560,10 +621,28 @@ def getGeoObjects(request, area_name, category_ids, status): data = '{"type": "FeatureCollection", "features":[%s]}' % ",".join(jsons) return HttpResponse(data) +def get_all_categories(request, area_name=None): + ''' + Get all available categories in JSON + ''' + context_data, redir = get_base_response(area_name) + area = context_data["area"] + subcategories = [] + if area: + subcategories = list(area.getCategories('A', + area_name=context_data['area_name'])) + else: + categories = SubCategory.getAvailable() + for cat, subcats in categories: + subcategories += subcats + subcats = [subcat.getJSONDict() for subcat in subcategories] + jsons = json.dumps({'categories':subcats}) + return HttpResponse(jsons) + def get_available_categories(request, area_name=None, area=None, status='A', force=None): ''' - Get categories for a designed area + Get category menu for a designed area ''' context_data, redir = get_base_response(area_name) area = context_data["area"] @@ -608,6 +687,16 @@ def get_available_categories(request, area_name=None, area=None, status='A', return render_to_response('chimere/blocks/categories.html', context_data, context_instance=RequestContext(request)) +def getCategory(request, area_name='', category_id=0): + ''' + Get the JSON for a category (mainly in order to get the description) + ''' + try: + category = SubCategory.objects.get(pk=category_id) + except ObjectDoesNotExist: + return HttpResponse('no results') + return HttpResponse(category.getJSON()) + def getTinyfiedUrl(request, parameters, area_name=''): ''' Get the tinyfied version of parameters @@ -648,6 +737,72 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return redir return HttpResponseRedirect(response_dct['extra_url'] + parameters) +def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, + transport='foot', speed=''): + ''' + Get the JSON for a route + ''' + try: + lon1, lat1 = float(lon1), float(lat1) + lon2, lat2 = float(lon2), float(lat2) + steps = [float(lonlat) for lonlat in lonlat_steps.split('_') if lonlat] + # regroup by 2 + steps = [(steps[i*2], steps[i*2+1]) for i in range(len(steps)/2)] + except ValueError: + return HttpResponse('no results') + jsons, desc, total = router.route(lon1, lat1, lon2, lat2, steps=steps, + transport=transport, speed=speed) + if not jsons: + return HttpResponse('no results') + jsonencoder = json.JSONEncoder() + total = jsonencoder.encode(total) + desc = jsonencoder.encode(desc) + + # get associated POIs + try: + route = GEOSGeometry(jsons[0]) + except OGRException: + return HttpResponse(_(u"Bad geometry"), status=500) + cats = SubCategory.objects.filter(routing_warn=True) + message = '' + if cats.count(): + st_string = '{"type":"Feature", "geometry":{ "type": "Point", '\ + '"coordinates": [ %f, %f ] }, "properties":{"icon_path":"%s",'\ + '"icon_width":%d, "icon_height":%d}}' + points = [(m.point, m.categories.all()[0].icon) + for m in list(Marker.objects.filter(status='A', + categories__in=cats, point__distance_lte=(route, D(m=15)) + ).all())] + for pt, icon in points: + st = st_string % (pt.x, pt.y, icon.image.url, icon.image.width, + icon.image.height) + jsons.append(st) + routes = Route.objects.filter(status='A', categories__in=cats, + route__crosses=route) + intersect = False + for rout in routes.intersection(route): + pts = rout.intersection + icon = rout.categories.all()[0].icon + if hasattr(pts, 'x'): + pts = [pts] + if pts: + pt = pts[0] + st = st_string % (pt.x, pt.y, icon.image.url, icon.image.width, + icon.image.height) + jsons.append(st) + if points or intersect: + message = getattr(settings, 'CHIMERE_ROUTING_WARN_MESSAGE', '') + if message: + message = ', "message":%s' % jsonencoder.encode( + "%s" % _(message)) + else: + message = '' + data = '{"properties":{"transport":%s, "total":%s, "description":%s}, '\ + '"type": "FeatureCollection", "features":[%s]%s}' % ( + jsonencoder.encode(transport), total, desc, ",".join(jsons), + message) + return HttpResponse(data) + def rss(request, area_name=''): ''' Redirect to RSS subscription page @@ -655,7 +810,8 @@ def rss(request, area_name=''): response_dct, redir = get_base_response(area_name) if redir: return redir - response_dct.update({'actions':actions, 'action_selected':('rss',), + response_dct.update({'actions':actions(response_dct['area_name']), + 'action_selected':('rss',), 'category_rss_feed':'',}) # If the form has been submited if request.method == "POST": diff --git a/chimere/widgets.py b/chimere/widgets.py index 2d0c189..4f09c62 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -27,6 +27,9 @@ from django.contrib.gis.db import models from django.contrib.gis.geos import fromstr from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse +from django.forms.widgets import RadioInput, RadioFieldRenderer +from django.utils.encoding import force_unicode +from django.utils.html import conditional_escape from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ from django.template.loader import render_to_string @@ -71,18 +74,23 @@ def get_map_layers(area_name=''): pass map_layers, default = [], None if area and area.layers.count(): - map_layers = [layer.layer_code + map_layers = [[layer.name, layer.layer_code, False] for layer in area.layers.order_by('arealayers__order').all()] def_layer = area.layers.filter(arealayers__default=True) if def_layer.count(): def_layer = def_layer.all()[0] for order, map_layer in enumerate(map_layers): - if map_layer == def_layer.layer_code: + if map_layer[1] == def_layer.layer_code: default = order + map_layers[order][2] = True + else: + map_layers[0][2] = True elif settings.CHIMERE_DEFAULT_MAP_LAYER: - map_layers = [settings.CHIMERE_DEFAULT_MAP_LAYER] + map_layers = [(_(u"Default layer"), settings.CHIMERE_DEFAULT_MAP_LAYER, + True)] else: - map_layers = ["new OpenLayers.Layer.OSM.Mapnik('Mapnik')"] + map_layers = [(u"Mapnik", "new OpenLayers.Layer.OSM.Mapnik('Mapnik')", + True)] return map_layers, default class ChosenSelectWidget(forms.Select): @@ -104,6 +112,41 @@ class ChosenSelectWidget(forms.Select): u"</script>\n" % kwargs['attrs']['id'] return mark_safe(rendered) +""" +JQuery UI button select widget. +""" +class ButtonRadioInput(RadioInput): + def render(self, name=None, value=None, attrs=None, choices=()): + name = name or self.name + value = value or self.value + attrs = attrs or self.attrs + if 'id' in self.attrs: + label_for = ' for="%s_%s"' % (self.attrs['id'], self.index) + else: + label_for = '' + choice_label = conditional_escape(force_unicode(self.choice_label)) + return mark_safe(u'%s <label%s>%s</label>' % (self.tag(), label_for, + choice_label)) +class ButtonRadioFieldRenderer(RadioFieldRenderer): + def __iter__(self): + for i, choice in enumerate(self.choices): + yield ButtonRadioInput(self.name, self.value, self.attrs.copy(), + choice, i) + def render(self): + return mark_safe(u'\n'.join([force_unicode(w) for w in self])) +class ButtonSelectWidget(forms.RadioSelect): + def __init__(self, *args, **kwargs): + self.renderer = ButtonRadioFieldRenderer + super(ButtonSelectWidget, self).__init__(*args, **kwargs) + + def render(self, *args, **kwargs): + rendered = "<div id='%s'>\n" % kwargs['attrs']['id'] + rendered += super(ButtonSelectWidget, self).render(*args, **kwargs) + rendered += u"\n<script type='text/javascript'>\n"\ + u" $('#%s').buttonset();\n"\ + u"</script>\n</div>\n" % kwargs['attrs']['id'] + return mark_safe(rendered) + class ImporterChoicesWidget(forms.Select): ''' Importer select widget. @@ -126,6 +169,33 @@ class TextareaWidgetBase(forms.Textarea): rendered = super(TextareaWidgetBase, self).render(*args, **kwargs) return mark_safe(rendered) +class FullTextareaWidget(TextareaWidgetBase): + """ + Manage the edition of a text using TinyMCE + """ + class Media: + js = ["%stiny_mce.js" % settings.TINYMCE_URL] + + def render(self, *args, **kwargs): + if 'attrs' not in kwargs: + kwargs['attrs'] = {} + if 'class' not in kwargs['attrs']: + kwargs['attrs']['class'] = '' + else: + kwargs['attrs']['class'] += ' ' + kwargs['attrs']['class'] += 'mceEditor' + rendered = super(FullTextareaWidget, self).render(*args, **kwargs) + rendered += u"""<script type='text/javascript'> +tinyMCE.init({ + mode : "textareas", + theme : "advanced", + relative_urls : false, + editor_selector : "mceEditor" +}); +</script> +""" + return mark_safe(rendered) + class TextareaWidget(TextareaWidgetBase): """ Manage the edition of a text using TinyMCE @@ -152,6 +222,27 @@ class DatePickerWidget(forms.TextInput): u"</script>\n" % kwargs['attrs']['id'] return mark_safe(rendered) +class NominatimWidget(forms.TextInput): + class Media: + js = ["%schimere/js/nominatim-widget.js" % settings.STATIC_URL] + def render(self, name, value, attrs=None, area_name=''): + tpl = u""" +<input type='hidden' name='nominatim_%(id)s_lat' id='nominatim_%(id)s_lat'/> +<input type='hidden' name='nominatim_%(id)s_lon' id='nominatim_%(id)s_lon'/> +<input type='text' class='nominatim-widget' name='nominatim_%(id)s' id='nominatim_%(id)s' value=""/> +<label class='nominatim-label' id='nominatim_%(id)s_label'> </label> +<script type='text/javascript'> +var default_nominatim_lbl = "%(label)s"; +var nominatim_url = "%(nominatim_url)s"; +$("#nominatim_%(id)s").val(default_nominatim_lbl); +$("#nominatim_%(id)s").click(function(){ + $("#nominatim_%(id)s").val(''); +}); +</script> +""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL, + 'label':_(u"Street, City, Country")} + return mark_safe(tpl) + class PointChooserWidget(forms.TextInput): """ Manage the edition of point on a map @@ -183,6 +274,7 @@ class PointChooserWidget(forms.TextInput): else: value = None map_layers, default_area = get_map_layers(area_name) + map_layers = [js for n, js, default in map_layers] #TODO: manage area return mark_safe( render_to_string('chimere/blocks/live_coordinates.html', @@ -238,7 +330,11 @@ class RouteChooserWidget(forms.TextInput): ''' tpl = getMapJS(area_name) map_layers, default_area = get_map_layers(area_name) + map_layers = [js for nm, js, default in map_layers] js = """ + var resolutions; + var zoomOffset; + var extra_url = "%s"; OpenLayers.ImgPath = '%schimere/img/'; var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:%s'); @@ -251,7 +347,7 @@ class RouteChooserWidget(forms.TextInput): chimere_init_options['edition'] = true; chimere_init_options['edition_type_is_route'] = true; chimere_init_options["checked_categories"] = []; - """ % ( reverse("chimere:index"), settings.STATIC_URL, + """ % (reverse("chimere:index"), settings.STATIC_URL, settings.CHIMERE_EPSG_DISPLAY_PROJECTION, settings.CHIMERE_EPSG_PROJECTION, settings.CHIMERE_DEFAULT_CENTER, settings.CHIMERE_DEFAULT_ZOOM, ", ".join(map_layers)) |