From 9d22e093dac0d30d6de797222952c1e5f938382c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 14 Aug 2012 18:29:38 +0200 Subject: Routing & UI improvment: first work on map menu * add a map menu on the main interface * add a new templatetag: map_menu * add CHIMERE_ENABLE_ROUTING to settings * add a routing settings (boolean) in jquery.chimere.js * manage zoomin, zoomout, center in jquery.chimere.js --- chimere/static/chimere/css/styles.css | 23 ++++++++++++ chimere/static/chimere/js/jquery.chimere.js | 48 +++++++++++++++++++++++++- chimere/templates/chimere/blocks/map_menu.html | 12 +++++++ chimere/templates/chimere/main_map.html | 1 + chimere/templatetags/chimere_tags.py | 5 +++ example_project/settings.py | 3 ++ 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 chimere/templates/chimere/blocks/map_menu.html diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index cba308e..92ecca6 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -410,6 +410,29 @@ ul#share li{ padding-top:0; } +#chimere_map_menu{ + z-index:4; + display:none; + position:absolute; + padding:0.5em; + background-color:#fff; + border:1px solid #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +#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; +} + .simple #panel{ top:5px; } diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index b2de3de..116f927 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -66,6 +66,7 @@ See the file COPYING for details. units: 'm', projection: new OpenLayers.Projection('EPSG:4326'), theme:null, + routing: false, // enable routing management 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 @@ -104,6 +105,8 @@ See the file COPYING for details. map_options['restrictedExtent'] = settings.restricted_extent; } + settings.current_position = null; + /* Create map object */ settings.map = map = new OpenLayers.Map(map_element, map_options); @@ -196,7 +199,7 @@ See the file COPYING for details. methods.loadGeoObjects(); // Hide popUp when clicking on map settings.map.events.register('click', settings.map, - helpers.hidePopup); + methods.displayMapMenu); } else { if (!settings.edition_type_is_route){ map.events.register('click', settings.map, @@ -208,8 +211,50 @@ See the file COPYING for details. settings.layerVectors, helpers.featureRouteCreated); } } + $('#chimere_map_menu #map_menu_zoomin').bind("click", + methods.zoomIn); + $('#chimere_map_menu #map_menu_zoomout').bind("click", + methods.zoomOut); + $('#map_menu_center').bind("click", methods.mapCenter); }, // end of init + // zoom in from the map 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); + }, + + /* + * Display menu on the map + */ + displayMapMenu: function(e) { + helpers.hidePopup(); + if ($('#chimere_map_menu').is(":visible")){ + $('#chimere_map_menu').hide(); + } else{ + settings.current_position = + 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 */ @@ -368,6 +413,7 @@ See the file COPYING for details. } else { + $('#chimere_map_menu').hide(); // Default popup if (feature.popup && feature.popup.visible()) { if (settings.current_popup == feature.popup) { diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html new file mode 100644 index 0000000..513d6ba --- /dev/null +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -0,0 +1,12 @@ +{% load i18n %} +
+ +
diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index f84b372..ae6578f 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -34,6 +34,7 @@ + {% map_menu %} {% map_params %} {% endblock %} {% block footer %} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index e7f7248..70dabaa 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -111,6 +111,11 @@ def head_chimere(context): } 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} + return context_data + @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) def map_params(context): context_data = {} diff --git a/example_project/settings.py b/example_project/settings.py index a7c14d5..9b25605 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -74,6 +74,9 @@ CHIMERE_OSM_PASSWORD = 'test' # encoding for shapefile import CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' +# enable routing in Chimère +CHIMERE_ENABLE_ROUTING = False + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From 12d8f2d9b97051056077e344499c765e1f95bda7 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 01:38:28 +0200 Subject: First working version of routing. * add an utilitary Routing class to manage different routing system * implement the routing with routino * add a view to manage routes * itinerary panel template * JS management of routing: * manage flag markers on the map * request the route when start and finish flag are set * display the route and the itinerary description * add of two flags images * itinerary panel CSS * french translation update --- chimere/locale/fr/LC_MESSAGES/django.po | 117 ++++++++++++----------- chimere/route.py | 87 +++++++++++++++++ chimere/static/chimere/css/styles.css | 45 +++++++-- chimere/static/chimere/img/flag-finish.png | Bin 0 -> 1652 bytes chimere/static/chimere/img/flag-start.png | Bin 0 -> 1165 bytes chimere/static/chimere/img/images_licences | 7 ++ chimere/static/chimere/js/jquery.chimere.js | 102 +++++++++++++++++++- chimere/templates/chimere/blocks/map_menu.html | 8 ++ chimere/templates/chimere/blocks/map_params.html | 1 + chimere/templatetags/chimere_tags.py | 2 + chimere/urls.py | 8 ++ chimere/views.py | 21 ++++ example_project/settings.py | 7 ++ 13 files changed, 337 insertions(+), 68 deletions(-) create mode 100644 chimere/route.py create mode 100644 chimere/static/chimere/img/flag-finish.png create mode 100644 chimere/static/chimere/img/flag-start.png diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index 53cf4d4..c188f77 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-02 20:40+0200\n" +"POT-Creation-Date: 2012-08-15 01:31+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" @@ -107,26 +107,26 @@ msgstr "Courriel (optionnel) " msgid "Object" msgstr "Objet" -#: forms.py:147 +#: forms.py:155 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:358 +#: forms.py:369 msgid "File" msgstr "Fichier" -#: forms.py:364 +#: forms.py:375 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:369 models.py:48 models.py:101 models.py:122 models.py:135 +#: forms.py:380 models.py:48 models.py:101 models.py:122 models.py:135 #: models.py:149 models.py:232 models.py:437 models.py:480 models.py:524 #: models.py:555 models.py:792 models.py:804 models.py:889 #: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 msgid "Name" msgstr "Nom" -#: forms.py:378 models.py:841 +#: forms.py:389 models.py:841 msgid "Area" msgstr "Zone" @@ -515,91 +515,91 @@ msgstr "Valeur" msgid "Property" msgstr "Propriété" -#: tasks.py:47 +#: tasks.py:61 msgid "Import pending" msgstr "Import en attente" -#: tasks.py:48 +#: tasks.py:62 msgid "Import processing" msgstr "Import en cours" -#: tasks.py:49 +#: tasks.py:63 msgid "Import successfuly done" msgstr "Import fait avec succès" -#: tasks.py:50 +#: tasks.py:64 #, python-format msgid " %(new)d new item(s), %(updated)d updated item(s)" msgstr " %(new)d nouveau(x) élément(s), %(updated)d élément(s) mis à jour" -#: tasks.py:51 +#: tasks.py:65 msgid "Import failed" msgstr "Import échoué" -#: tasks.py:52 +#: tasks.py:66 msgid "Import canceled" msgstr "Import annulé" -#: tasks.py:53 +#: tasks.py:67 msgid "Export pending" msgstr "Export en attente" -#: tasks.py:54 +#: tasks.py:68 msgid "Export processing" msgstr "Export en cours" -#: tasks.py:55 +#: tasks.py:69 msgid "Export successfuly done" msgstr "Export réalisé avec succès" -#: tasks.py:56 +#: tasks.py:70 #, python-format msgid " %(updated)d updated item(s)" msgstr " %(updated)d éléments mis à jour" -#: tasks.py:57 +#: tasks.py:71 msgid "Export failed" msgstr "Export échoué" -#: tasks.py:58 +#: tasks.py:72 msgid "Export canceled" msgstr "Export annulé" -#: utils.py:104 utils.py:152 +#: utils.py:113 utils.py:161 msgid "Bad zip file" msgstr "Mauvais fichier zip" -#: utils.py:155 +#: utils.py:164 msgid "Missing file(s) inside the zip file" msgstr "Fichier(s) manquant(s) dans l'archive zip" -#: utils.py:284 +#: utils.py:293 msgid "Error while reading the data source." msgstr "Erreur lors de la lecture de la source." -#: utils.py:319 +#: utils.py:328 msgid "Type of geographic item of this shapefile is not managed by Chimère." msgstr "" "Les types des éléments géographiques de ce fichier Shapefile ne sont pas " "gérés par Chimère." -#: utils.py:400 +#: utils.py:385 msgid "Could not create file!" msgstr "Ne peut pas créer le fichier !" -#: utils.py:411 +#: utils.py:396 msgid "Failed to create field" msgstr "Ne peut pas créer un champ" -#: utils.py:482 +#: utils.py:467 msgid "Nothing to import" msgstr "Rien à importer" -#: utils.py:562 +#: utils.py:547 msgid "New items imported - validate them before exporting" msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter" -#: utils.py:564 +#: utils.py:549 msgid "" "There are items from a former import not yet validated - validate them " "before exporting" @@ -607,23 +607,23 @@ msgstr "" "Il y a des éléments d'un import précédent pas encore validé - Validez les " "avant d'exporter" -#: utils.py:574 +#: utils.py:559 msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:223 +#: views.py:226 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:302 +#: views.py:305 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:424 +#: views.py:427 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:427 +#: views.py:430 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." @@ -632,15 +632,15 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:431 +#: views.py:434 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:562 +#: views.py:565 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:669 +#: views.py:690 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" @@ -790,10 +790,6 @@ msgstr "Partager sur" msgid "Share" msgstr "Partager" -#: templates/chimere/detail.html:37 -msgid "Submit a modification" -msgstr "Proposer une modification" - #: templates/chimere/edit.html:20 msgid "Error" msgstr "Erreur" @@ -873,6 +869,32 @@ msgstr "Ce site utilise Chimère" msgid "Map" msgstr "Carte" +#: templates/chimere/blocks/map_menu.html:5 +msgctxt "routing" +msgid "From" +msgstr "En partir" + +#: templates/chimere/blocks/map_menu.html:6 +msgctxt "routing" +msgid "To" +msgstr "Y aller" + +#: templates/chimere/blocks/map_menu.html:8 +msgid "Zoom in" +msgstr "Zoomer en avant" + +#: templates/chimere/blocks/map_menu.html:9 +msgid "Zoom out" +msgstr "Zoomer en arrière" + +#: templates/chimere/blocks/map_menu.html:10 +msgid "Center the map here" +msgstr "Centrer la carte ici" + +#: templates/chimere/blocks/map_menu.html:16 +msgid "Itinerary" +msgstr "Itinéraire" + #: templates/chimere/blocks/map_params.html:6 msgid "Permalink" msgstr "Lien permanent" @@ -947,20 +969,3 @@ msgstr "Choisir une zone pré-définie" msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" -#~ msgid "Categorys" -#~ msgstr "Catégories" - -#~ msgid "Theme" -#~ msgstr "Thème" - -#~ msgid "Subtheme" -#~ msgstr "Sous-thème" - -#~ msgid "Subthemes" -#~ msgstr "Sous-thèmes" - -#~ msgid "Themes" -#~ msgstr "Thèmes" - -#~ msgid "Site name" -#~ msgstr "Nom du site" diff --git a/chimere/route.py b/chimere/route.py new file mode 100644 index 0000000..efc6763 --- /dev/null +++ b/chimere/route.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 Étienne Loks +# + +# 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 . + +# 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.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(""), re.compile(""), + re.compile("")] + def route(self, lon1, lat1, lon2, lat2, session_id='', transport='foot'): + ''' + 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, + "--lat2=%0.15f" % lat2, + "--lon2=%0.15f" % lon2 + ] + tmp_dir = tempfile.mkdtemp(prefix='chimere_') + os.sep + p = Popen(args, stdout=PIPE, cwd=tmp_dir) + p.communicate() + ds = DataSource(tmp_dir + 'shortest-track.gpx') + if not ds: + return [], 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()) + desc.append('
') + desc = BeautifulSoup('\n'.join(desc)).prettify() + shutil.rmtree(tmp_dir) + return res, desc +router = None +if settings.CHIMERE_ROUTING_ENGINE['ENGINE'] == 'routino': + router = RoutinoRouter() + diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 92ecca6..28dafd8 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -15,7 +15,8 @@ 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, +#chimere_itinerary td.l{ color:#fff; } @@ -30,7 +31,8 @@ body, h2, h3, th, .ui-widget-header, .action li.selected, #no-js-message, #content .olControlLayerSwitcher .layersDiv, -#content .olControlLayerSwitcher span{ +#content .olControlLayerSwitcher span, +#chimere_itinerary td.l{ background-color:#449506; } @@ -39,7 +41,7 @@ body, h2, h3, th, } fieldset, .action li, #content, -#map-footer, #panel, #areas, +#map-footer, #panel, #chimere_itinerary_panel, #areas, #welcome, #detail, .detail_footer a, #main-map, .window{ background-color:#FFF; @@ -61,7 +63,7 @@ div.warning, .errorlist{ div.warning, #content, .action li.selected, -#panel, #map-footer, +#panel, #map-footer, #chimere_itinerary_panel, #utils-div{ border:1px solid #327e04; } @@ -76,7 +78,7 @@ div.warning, opacity:0.9; } -#panel, #areas, #detail, #category_detail{ +#panel, #areas, #detail, #category_detail, #chimere_itinerary_panel{ opacity:0.8; } @@ -410,6 +412,33 @@ ul#share li{ padding-top:0; } +#chimere_itinerary_panel{ + position:absolute; + z-index:5; + top:50px; + left:50px; + width:300px; + padding:0.5em; + padding-top:0; + display:none; +} + +#chimere_itinerary{ + height:250px; + overflow:auto; + padding:0.2em 1em; + font-size:0.9em; +} + +#chimere_itinerary td.l{ + padding:6px; +} + +#chimere_itinerary span.j{ + font-style:italic; +} + + #chimere_map_menu{ z-index:4; display:none; @@ -417,9 +446,9 @@ ul#share li{ padding:0.5em; background-color:#fff; border:1px solid #bbb; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + -webkit-border-radius: 0 8px 8px 8px; + -moz-border-radius: 0 8px 8px 8px; + border-radius: 0 8px 8px 8px; } #chimere_map_menu ul, #chimere_map_menu li{ diff --git a/chimere/static/chimere/img/flag-finish.png b/chimere/static/chimere/img/flag-finish.png new file mode 100644 index 0000000..04bfa1d Binary files /dev/null and b/chimere/static/chimere/img/flag-finish.png differ diff --git a/chimere/static/chimere/img/flag-start.png b/chimere/static/chimere/img/flag-start.png new file mode 100644 index 0000000..c93f2a3 Binary files /dev/null and b/chimere/static/chimere/img/flag-start.png differ diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 0e732fc..000fdf0 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -30,3 +30,10 @@ Url 2: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg Author: Sbrools Licence: Public domain Url: https://commons.wikimedia.org/wiki/File:8thNote.svg + +* Flags image credit (flag-start.png, flag-finish.png) + +Author: FatCow Web Hosting +Licence: Creative Commons Attribution 3.0 United States license +Url: https://upload.wikimedia.org/wikipedia/commons/6/64/Farm-Fresh_flag_finish.png + https://upload.wikimedia.org/wikipedia/commons/c/cb/Farm-Fresh_flag_1.png diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 116f927..ed0ca02 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -211,11 +211,30 @@ See the file COPYING for details. settings.layerVectors, helpers.featureRouteCreated); } } - $('#chimere_map_menu #map_menu_zoomin').bind("click", - methods.zoomIn); - $('#chimere_map_menu #map_menu_zoomout').bind("click", - methods.zoomOut); + $('#map_menu_zoomin').bind("click", methods.zoomIn); + $('#map_menu_zoomout').bind("click", methods.zoomOut); $('#map_menu_center').bind("click", methods.mapCenter); + if (settings.routing){ + settings.routing_start = null; + settings.routing_end = null; + settings.icon_start = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-start.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_end = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-finish.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + $('#map_menu_from').bind("click", methods.routingFrom); + $('#map_menu_to').bind("click", methods.routingTo); + settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); + settings.map.addLayer(settings.layerRoute); + settings.layerRoute.setOpacity(0.8); + settings.layerRouteMarker = new OpenLayers.Layer.Markers( + 'Route markers'); + settings.map.addLayer(settings.layerRouteMarker); + settings.layerRouteMarker.setOpacity(0.8); + } }, // end of init // zoom in from the map menu @@ -479,6 +498,81 @@ See the file COPYING for details. settings.current_feature.geometry = linestring; settings.layerVectors.addFeatures([settings.current_feature]); }, + // set the start point for routing + routingFrom: function(){ + $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').hide(); + settings.routing_start = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + if (settings.routing_end) methods.route(); + }, + + // set the finish point for routing + routingTo: function(){ + $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').hide(); + settings.routing_end = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + if (settings.routing_start) methods.route(); + }, + + // display a route + route: function(){ + if (!settings.routing_start || !settings.routing_end){ + return; + } + var start = settings.routing_start.lonlat.clone().transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + var end = settings.routing_end.lonlat.clone().transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + var uri = extra_url + "route/" + + start.lon + '_' + + start.lat + '_' + + end.lon + '_' + + end.lat; + $.ajax({url: uri, + dataType: "json", + success: function (data) { + settings.layerRoute.removeAllFeatures(); + for (var i = 0; i < data.features.length; i++) { + methods.putRoute(data.features[i]); + } + $('#chimere_itinerary').html( + data.properties.description); + $('#chimere_itinerary_panel').show(); + }, + error: function (data) { + settings.layerRoute.removeAllFeatures(); + } + }); + + }, + /* + Put a route on the map + */ + putRoute: function(polyline) { + var point_array = new Array(); + for (i=0; i{% trans "Center the map here" %} + +{% if routing %} +
+

{% trans "Itinerary" %}

+
+
+
+{% endif%} diff --git a/chimere/templates/chimere/blocks/map_params.html b/chimere/templates/chimere/blocks/map_params.html index c8f97eb..1afd722 100644 --- a/chimere/templates/chimere/blocks/map_params.html +++ b/chimere/templates/chimere/blocks/map_params.html @@ -5,6 +5,7 @@ chimere_init_options["map_layers"] = [{{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}}); diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 70dabaa..5256518 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -123,6 +123,8 @@ def map_params(context): 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 settings.CHIMERE_ENABLE_ROUTING \ + else 'none' 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) diff --git a/chimere/urls.py b/chimere/urls.py index a232382..ad88e32 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -51,6 +51,14 @@ if settings.CHIMERE_FEEDS: LatestPOIsByZoneID(), name='feeds-areaid'), ) +if settings.CHIMERE_ENABLE_ROUTING: + urlpatterns += patterns('chimere.views', + url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', + 'route', name="route"), + ) + urlpatterns += patterns('chimere.views', url(r'^charte/?$', 'charte', name="charte"), url(r'^(?P[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', name="contact"), diff --git a/chimere/views.py b/chimere/views.py index 824d912..4af6120 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -26,6 +26,7 @@ Views of the project import datetime from itertools import groupby +import simplejson from django.conf import settings from django.core import serializers @@ -49,6 +50,8 @@ from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \ FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\ notifyStaff, AreaForm +from chimere.route import router + def get_base_uri(request): base_uri = 'http://' if 'HTTP_REFERER' in request.META: @@ -623,6 +626,24 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return redir return HttpResponseRedirect(response_dct['extra_url'] + parameters) +def route(request, area_name, lon1, lat1, lon2, lat2, transport='foot'): + ''' + Get the JSON for a route + ''' + try: + lon1, lat1 = float(lon1), float(lat1) + lon2, lat2 = float(lon2), float(lat2) + except ValueError: + return HttpResponse('no results') + jsons, desc = router.route(lon1, lat1, lon2, lat2, transport=transport, + session_id=request.session.session_key) + if not jsons: + return HttpResponse('no results') + jsonencoder = simplejson.JSONEncoder() + data = '{"properties":{"description":%s}, "type": "FeatureCollection",'\ + '"features":[%s]}' % (jsonencoder.encode(desc), ",".join(jsons)) + return HttpResponse(data) + def rss(request, area_name=''): ''' Redirect to RSS subscription page diff --git a/example_project/settings.py b/example_project/settings.py index 9b25605..ead2c93 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -77,6 +77,13 @@ CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' # enable routing in Chimère CHIMERE_ENABLE_ROUTING = False +# available routing engine: 'routino' +CHIMERE_ROUTING_ENGINE = { + 'ENGINE': 'routino', + 'PATH': '/usr/local/src/web/bin/router', + 'DB_PATH': '/var/local/routino/', +} + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From 4aa505b2b54bb07fd322fb234da47503b18434b5 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 17:28:38 +0200 Subject: Minor changes on routing presentation --- chimere/route.py | 4 ++-- chimere/static/chimere/css/styles.css | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/chimere/route.py b/chimere/route.py index efc6763..207232b 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -72,12 +72,12 @@ class RoutinoRouter(Router): res = [] for multiline in multilines: res += [geom.geojson for geom in multiline] - desc = [''] + 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()) - desc.append('
') + desc = [''] + desc[1:-2] + [desc[-1], '
'] desc = BeautifulSoup('\n'.join(desc)).prettify() shutil.rmtree(tmp_dir) return res, desc diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 28dafd8..f569d8f 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -431,13 +431,19 @@ ul#share li{ } #chimere_itinerary td.l{ - padding:6px; + padding:5px; + width:55px; } #chimere_itinerary span.j{ font-style:italic; } +#chimere_itinerary span.t, +#chimere_itinerary span.b +{ + text-transform: lowercase; +} #chimere_map_menu{ z-index:4; -- cgit v1.2.3 From 551acb05271dde226267ba5c1bed5db44523eae2 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 18:41:43 +0200 Subject: Use JQuery UI dialog for itinerary detail --- chimere/static/chimere/css/styles.css | 22 ++-------------------- chimere/static/chimere/js/jquery.chimere.js | 9 ++++++--- chimere/templates/chimere/blocks/map_menu.html | 13 +++++++++++-- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index f569d8f..9621344 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -63,7 +63,7 @@ div.warning, .errorlist{ div.warning, #content, .action li.selected, -#panel, #map-footer, #chimere_itinerary_panel, +#panel, #map-footer, #utils-div{ border:1px solid #327e04; } @@ -412,27 +412,9 @@ ul#share li{ padding-top:0; } -#chimere_itinerary_panel{ - position:absolute; - z-index:5; - top:50px; - left:50px; - width:300px; - padding:0.5em; - padding-top:0; - display:none; -} - -#chimere_itinerary{ - height:250px; - overflow:auto; - padding:0.2em 1em; - font-size:0.9em; -} - #chimere_itinerary td.l{ padding:5px; - width:55px; + width:60px; } #chimere_itinerary span.j{ diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index ed0ca02..fcf34f5 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -501,7 +501,8 @@ See the file COPYING for details. // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').hide(); + //$('#chimere_itinerary_panel').hide(); + $('#chimere_itinerary_panel').dialog('close'); settings.routing_start = new OpenLayers.Marker( settings.current_position.clone(), settings.icon_start); @@ -512,7 +513,8 @@ See the file COPYING for details. // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').hide(); + //$('#chimere_itinerary_panel').hide(); + $('#chimere_itinerary_panel').dialog('close'); settings.routing_end = new OpenLayers.Marker( settings.current_position.clone(), settings.icon_end); @@ -545,7 +547,8 @@ See the file COPYING for details. } $('#chimere_itinerary').html( data.properties.description); - $('#chimere_itinerary_panel').show(); + //$('#chimere_itinerary_panel').show(); + $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { settings.layerRoute.removeAllFeatures(); diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index 4c78a5b..52a4107 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -12,9 +12,18 @@ {% if routing %} -
-

{% trans "Itinerary" %}

+
+ {% endif%} -- cgit v1.2.3 From 8066268b131bbf7ac829e83ca7849e9752dcc6e6 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:10:57 +0200 Subject: Improve routing: manage steps * Manage steps in routing core * Add extra parameters for steps in urls.py * Modify the view to parse steps and send them to the routing core * Manage steps in JS (add many step flags and send a correct request to the view) * Manage a clear itinerary action in JS * Add a new flag image for steps * CSS improvement --- chimere/route.py | 12 +++-- chimere/static/chimere/css/styles.css | 21 +++++++++ chimere/static/chimere/img/flag-step.png | Bin 0 -> 1256 bytes chimere/static/chimere/img/images_licences | 7 +-- chimere/static/chimere/js/jquery.chimere.js | 62 +++++++++++++++++++------ chimere/templates/chimere/blocks/map_menu.html | 2 + chimere/urls.py | 1 + chimere/views.py | 10 ++-- 8 files changed, 93 insertions(+), 22 deletions(-) create mode 100644 chimere/static/chimere/img/flag-step.png diff --git a/chimere/route.py b/chimere/route.py index 207232b..bc08a39 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -39,7 +39,7 @@ class Router: class RoutinoRouter(Router): re_desc = [re.compile(""), re.compile(""), re.compile("")] - def route(self, lon1, lat1, lon2, lat2, session_id='', transport='foot'): + def route(self, lon1, lat1, lon2, lat2, steps=[], transport='foot'): ''' Get a list of geojson polylines and route description ''' @@ -53,9 +53,15 @@ class RoutinoRouter(Router): "--output-gpx-track", "--lat1=%0.15f" % lat1, "--lon1=%0.15f" % lon1, - "--lat2=%0.15f" % lat2, - "--lon2=%0.15f" % lon2 ] + 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() diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 9621344..a118d54 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -412,11 +412,24 @@ ul#share li{ padding-top:0; } +#chimere_itinerary table +{ + border-collapse:collapse; +} + +#chimere_itinerary td{ + border:8px solid #fff; +} + #chimere_itinerary td.l{ padding:5px; width:60px; } +#chimere_itinerary td.r{ + font-size:0.8em; +} + #chimere_itinerary span.j{ font-style:italic; } @@ -439,6 +452,14 @@ ul#share li{ 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; diff --git a/chimere/static/chimere/img/flag-step.png b/chimere/static/chimere/img/flag-step.png new file mode 100644 index 0000000..5556c94 Binary files /dev/null and b/chimere/static/chimere/img/flag-step.png differ diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 000fdf0..03d63dc 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -31,9 +31,10 @@ Author: Sbrools Licence: Public domain Url: https://commons.wikimedia.org/wiki/File:8thNote.svg -* Flags image credit (flag-start.png, flag-finish.png) +* 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/6/64/Farm-Fresh_flag_finish.png - https://upload.wikimedia.org/wikipedia/commons/c/cb/Farm-Fresh_flag_1.png +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/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index fcf34f5..664ef15 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -216,17 +216,24 @@ See the file COPYING for details. $('#map_menu_center').bind("click", methods.mapCenter); if (settings.routing){ settings.routing_start = null; + settings.routing_steps = new Array(); settings.routing_end = null; settings.icon_start = new OpenLayers.Icon( STATIC_URL + "chimere/img/flag-start.png", new OpenLayers.Size(32, 32), new OpenLayers.Pixel(0, -32)); + settings.icon_step = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-step.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); settings.icon_end = new OpenLayers.Icon( STATIC_URL + "chimere/img/flag-finish.png", new OpenLayers.Size(32, 32), new OpenLayers.Pixel(0, -32)); $('#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.layerRoute.setOpacity(0.8); @@ -501,7 +508,7 @@ See the file COPYING for details. // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); - //$('#chimere_itinerary_panel').hide(); + $('#map_menu_clear').show(); $('#chimere_itinerary_panel').dialog('close'); settings.routing_start = new OpenLayers.Marker( settings.current_position.clone(), @@ -510,10 +517,23 @@ See the file COPYING for details. if (settings.routing_end) methods.route(); }, + // add a step point for routing + routingAddStep: function(){ + $('#chimere_map_menu').hide(); + $('#map_menu_clear').show(); + $('#chimere_itinerary_panel').dialog('close'); + 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 (settings.routing_end && settings.routing_start) methods.route(); + }, + // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); - //$('#chimere_itinerary_panel').hide(); + $('#map_menu_clear').show(); $('#chimere_itinerary_panel').dialog('close'); settings.routing_end = new OpenLayers.Marker( settings.current_position.clone(), @@ -522,22 +542,39 @@ See the file COPYING for details. if (settings.routing_start) methods.route(); }, + // clear the current itinerary + routingClear: function(){ + $('#chimere_map_menu').hide(); + $('#map_menu_clear').hide(); + $('#chimere_itinerary_panel').dialog('close'); + settings.layerRoute.removeAllFeatures(); + settings.layerRouteMarker.clearMarkers(); + settings.routing_start = null; + settings.routing_end = null; + settings.routing_steps = new Array(); + }, + // display a route route: function(){ if (!settings.routing_start || !settings.routing_end){ return; } - var start = settings.routing_start.lonlat.clone().transform( - settings.map.getProjectionObject(), - EPSG_DISPLAY_PROJECTION); - var end = settings.routing_end.lonlat.clone().transform( + 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/" + for (var i = 0; i < steps.length; i++) { + var step = steps[i].transform( settings.map.getProjectionObject(), EPSG_DISPLAY_PROJECTION); - var uri = extra_url + "route/" - + start.lon + '_' - + start.lat + '_' - + end.lon + '_' - + end.lat; + if (i > 0){ + uri += '_'; + } + uri += step.lon + '_' + step.lat; + } $.ajax({url: uri, dataType: "json", success: function (data) { @@ -547,8 +584,7 @@ See the file COPYING for details. } $('#chimere_itinerary').html( data.properties.description); - //$('#chimere_itinerary_panel').show(); - $('#chimere_itinerary_panel').dialog('open'); + $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { settings.layerRoute.removeAllFeatures(); diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index 52a4107..e541c1e 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -3,7 +3,9 @@
    {% if routing %}
  • {% trans "From" context "routing" %}
  • +
  • {% trans "Add a step" context "routing" %}
  • {% trans "To" context "routing" %}
  • +
  • {% trans "Clear the itinerary" context "routing" %}
  • {% endif%}
  • {% trans "Zoom in" %}
  • {% trans "Zoom out" %}
  • diff --git a/chimere/urls.py b/chimere/urls.py index ad88e32..aec82fb 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -55,6 +55,7 @@ if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ + r'(?P([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', 'route', name="route"), ) diff --git a/chimere/views.py b/chimere/views.py index 4af6120..308fb14 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -626,17 +626,21 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return redir return HttpResponseRedirect(response_dct['extra_url'] + parameters) -def route(request, area_name, lon1, lat1, lon2, lat2, transport='foot'): +def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, + transport='foot'): ''' 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 = router.route(lon1, lat1, lon2, lat2, transport=transport, - session_id=request.session.session_key) + jsons, desc = router.route(lon1, lat1, lon2, lat2, steps=steps, + transport=transport) if not jsons: return HttpResponse('no results') jsonencoder = simplejson.JSONEncoder() -- cgit v1.2.3 From ee8eb14ba2c29c2f1a451472e5338492dcfb9b47 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:27:37 +0200 Subject: Improve itinerary layout * create a proper templatetag for routing * add a button to show the routing dialog * some cleaning in the css file --- chimere/static/chimere/css/styles.css | 14 +++----------- chimere/templates/chimere/blocks/map_menu.html | 17 ----------------- chimere/templates/chimere/blocks/routing.html | 21 +++++++++++++++++++++ chimere/templates/chimere/main_map.html | 1 + chimere/templatetags/chimere_tags.py | 5 +++++ 5 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 chimere/templates/chimere/blocks/routing.html diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index a118d54..c7a4c05 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -589,26 +589,18 @@ p.warning{ } -#welcome_button, +a#welcome_button, +a#routing_button, #permalink{ display: block; - text-align:center; margin:0.3em; padding:0.2em; -} - -a#welcome_button, -#permalink{ + width:100%; font-size:14px; text-align:center; text-decoration:none; } -#welcome_button, -#permalink{ - width:100%; -} - /* forms */ table.inline-table{ diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index e541c1e..38fb4a8 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -12,20 +12,3 @@
  • {% trans "Center the map here" %}
- -{% if routing %} -
-
-
-
- -{% endif%} diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html new file mode 100644 index 0000000..226480b --- /dev/null +++ b/chimere/templates/chimere/blocks/routing.html @@ -0,0 +1,21 @@ +{% load i18n %} +{% if routing %} +{% trans "Itinerary"%} +
+
+
+
+ +{% endif%} diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index ae6578f..8cb7da3 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -22,6 +22,7 @@ {% if areas_visible %} {% display_areas %} {% endif %} + {% routing %} {% display_news news_visible %} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 5256518..51e64bf 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -116,6 +116,11 @@ def map_menu(context): context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} return context_data +@register.inclusion_tag('chimere/blocks/routing.html', takes_context=True) +def routing(context): + context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} + return context_data + @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) def map_params(context): context_data = {} -- cgit v1.2.3 From e0029f8e8d11736b41046f2a7390b6f5303fbb58 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:30:59 +0200 Subject: Update french translation with routing --- chimere/locale/fr/LC_MESSAGES/django.po | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index c188f77..8ba4b43 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-15 01:31+0200\n" +"POT-Creation-Date: 2012-08-15 20:29+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" @@ -640,7 +640,7 @@ msgstr "Erreur temporaire. Réenvoyez votre message plus tard." msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:690 +#: views.py:694 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" @@ -876,25 +876,31 @@ 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:9 +#: templates/chimere/blocks/map_menu.html:11 msgid "Zoom out" msgstr "Zoomer en arrière" -#: templates/chimere/blocks/map_menu.html:10 +#: templates/chimere/blocks/map_menu.html:12 msgid "Center the map here" msgstr "Centrer la carte ici" -#: templates/chimere/blocks/map_menu.html:16 -msgid "Itinerary" -msgstr "Itinéraire" - #: templates/chimere/blocks/map_params.html:6 msgid "Permalink" msgstr "Lien permanent" @@ -905,6 +911,11 @@ msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." +#: templates/chimere/blocks/routing.html:3 +#: templates/chimere/blocks/routing.html:13 +msgid "Itinerary" +msgstr "Itinéraire" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -968,4 +979,3 @@ msgstr "Choisir une zone pré-définie" #: templates/chimere/feeds/rss.html:64 msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" - -- cgit v1.2.3 From 502cc25a0dc57a61289c245d653f96e2b3009efa Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 17 Aug 2012 13:13:15 +0200 Subject: Improve routing interface and functionalities * fix POI clicking * create a nominatim widget to get coordinates from text * create a JQuery UI button select widget * create a routing form to get itinerary from a textual form * CSS for the routing form * Reverse nominatim: when a point is get for routing on the map label for this point is get from nominatim * Add transport management by user choice * Update french translation --- chimere/forms.py | 18 ++- chimere/locale/fr/LC_MESSAGES/django.po | 91 ++++++++++----- chimere/static/chimere/css/styles.css | 58 ++++++++-- chimere/static/chimere/img/images_licences | 6 +- chimere/static/chimere/js/jquery.chimere.js | 155 +++++++++++++++++++------- chimere/static/chimere/js/nominatim-widget.js | 41 +++++++ chimere/templates/chimere/blocks/routing.html | 37 +++++- chimere/templatetags/chimere_tags.py | 3 +- chimere/urls.py | 4 +- chimere/views.py | 4 +- chimere/widgets.py | 53 +++++++++ example_project/settings.py | 14 +++ 12 files changed, 394 insertions(+), 90 deletions(-) create mode 100644 chimere/static/chimere/js/nominatim-widget.js diff --git a/chimere/forms.py b/chimere/forms.py index e3486c0..c036911 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -35,7 +35,7 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ PictureFile, Importer from chimere.widgets import AreaField, PointField, TextareaWidget, \ - DatePickerWidget + DatePickerWidget, ButtonSelectWidget, NominatimWidget from datetime import timedelta, datetime, tzinfo @@ -438,3 +438,19 @@ class AreaForm(AreaAdminForm): class Meta: model = Area +class RoutingForm(forms.Form): + transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, + choices=settings.CHIMERE_ROUTING_TRANSPORT, + initial=settings.CHIMERE_ROUTING_TRANSPORT[0][0]) + 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) + + def __init__(self, *args, **kwargs): + super(RoutingForm, self).__init__(*args, **kwargs) + if not settings.CHIMERE_ROUTING_SPEEDS: + self.fields.pop('speed') + 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 8ba4b43..9335b42 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-15 20:29+0200\n" +"POT-Creation-Date: 2012-08-17 13:12+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" @@ -130,6 +130,18 @@ msgstr "Nom" msgid "Area" msgstr "Zone" +#: forms.py:445 +msgid "Start" +msgstr "Départ" + +#: forms.py:446 +msgid "Finish" +msgstr "Arrivée :" + +#: forms.py:447 +msgid "Speed" +msgstr "Vitesse" + #: models.py:49 models.py:123 models.py:150 models.py:241 models.py:441 #: models.py:810 models.py:891 msgid "Available" @@ -611,19 +623,19 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:226 +#: views.py:228 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:305 +#: views.py:307 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:427 +#: views.py:429 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:430 +#: views.py:432 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." @@ -632,48 +644,48 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:434 +#: views.py:436 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:565 +#: views.py:567 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:694 +#: views.py:696 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:187 +#: widgets.py:240 msgid "Latitude" msgstr "Latitude" -#: widgets.py:187 +#: widgets.py:240 msgid "Longitude" msgstr "Longitude" -#: widgets.py:212 +#: widgets.py:265 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:262 +#: widgets.py:315 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:263 +#: widgets.py:316 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:265 +#: widgets.py:318 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:266 +#: widgets.py:319 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:267 +#: widgets.py:320 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -681,7 +693,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:269 +#: widgets.py:322 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -689,17 +701,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:274 +#: widgets.py:327 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:275 +#: widgets.py:328 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:276 +#: widgets.py:329 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -707,7 +719,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:278 +#: widgets.py:331 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -716,33 +728,33 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:285 +#: widgets.py:338 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:288 +#: widgets.py:341 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:289 +#: widgets.py:342 msgid "or" msgstr "ou" -#: widgets.py:294 +#: widgets.py:347 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:317 +#: widgets.py:370 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:317 +#: widgets.py:370 msgid "Draw" msgstr "Tracer" -#: widgets.py:442 +#: widgets.py:495 msgid "Select..." msgstr "Sélectionner..." @@ -911,11 +923,27 @@ msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." -#: templates/chimere/blocks/routing.html:3 -#: templates/chimere/blocks/routing.html:13 +#: templates/chimere/blocks/routing.html:4 +#: templates/chimere/blocks/routing.html:40 msgid "Itinerary" msgstr "Itinéraire" +#: templates/chimere/blocks/routing.html:19 +msgid "Modify" +msgstr "Modifier" + +#: templates/chimere/blocks/routing.html:22 +msgid "New search" +msgstr "Nouvelle recherche" + +#: templates/chimere/blocks/routing.html:27 +msgid "Start:" +msgstr "Départ :" + +#: templates/chimere/blocks/routing.html:31 +msgid "Finish:" +msgstr "Arrivée :" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -979,3 +1007,6 @@ msgstr "Choisir une zone pré-définie" #: templates/chimere/feeds/rss.html:64 msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" + +#~ msgid "End" +#~ msgstr "Fin" diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index c7a4c05..e551ac6 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -406,36 +406,69 @@ ul#share li{ top:50px; right:18px; width:300px; - bottom:44px; + max-height:300px; overflow:auto; padding:0.5em; padding-top:0; } -#chimere_itinerary table +#chimere_itinerary_panel, +#chimere_itinerary{ + display:none; +} + +#chimere_itinerary_panel label{ + color:#000; +} + +#chimere_itinerary_panel p +{ + margin:0.5em; +} + +.itinerary_label{ + font-size:0.9em; + padding-top:0.5em; + font-style:italic; +} + +.itinerary_label.label{ + font-style:normal; + font-weight:bold; +} + + +#chimere_itinerary_content{ + overflow:auto; + height:190px; + margin-top:10px; +} + +#chimere_itinerary_content table { border-collapse:collapse; } -#chimere_itinerary td{ - border:8px solid #fff; +#chimere_itinerary_content table td{ + border:1px solid #333; } -#chimere_itinerary td.l{ +#chimere_itinerary_content td.l{ padding:5px; width:60px; } -#chimere_itinerary td.r{ +#chimere_itinerary_content td.r{ font-size:0.8em; + padding:0.8em; } -#chimere_itinerary span.j{ +#chimere_itinerary_content span.j{ font-style:italic; } -#chimere_itinerary span.t, -#chimere_itinerary span.b +#chimere_itinerary_content span.t, +#chimere_itinerary_content span.b { text-transform: lowercase; } @@ -471,6 +504,13 @@ ul#share li{ background-color:#ccc; } +.nominatim-label{ + display:block; + font-size:0.9em; + font-weight:bold; + height:2.8em; +} + .simple #panel{ top:5px; } diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 03d63dc..cbc9307 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,7 +16,7 @@ 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 @@ -24,7 +24,7 @@ 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 -* Quaver image credit +* Quaver image credit (8thNote.png) * An 8th-note. Author: Sbrools diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 664ef15..f46f3eb 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -156,6 +156,40 @@ See the file COPYING for details. } 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; + settings.icon_start = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-start.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_step = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-step.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_end = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-finish.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + $('#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.layerRoute.setOpacity(0.8); + settings.layerRouteMarker = new OpenLayers.Layer.Markers( + 'Route markers'); + settings.map.addLayer(settings.layerRouteMarker); + settings.layerRouteMarker.setOpacity(0.8); + } /* Vectors layer */ settings.layerVectors = new OpenLayers.Layer.Vector("Vector Layer"); settings.map.addLayer(settings.layerVectors); @@ -211,37 +245,6 @@ See the file COPYING for details. settings.layerVectors, helpers.featureRouteCreated); } } - $('#map_menu_zoomin').bind("click", methods.zoomIn); - $('#map_menu_zoomout').bind("click", methods.zoomOut); - $('#map_menu_center').bind("click", methods.mapCenter); - if (settings.routing){ - settings.routing_start = null; - settings.routing_steps = new Array(); - settings.routing_end = null; - settings.icon_start = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-start.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - settings.icon_step = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-step.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - settings.icon_end = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-finish.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - $('#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.layerRoute.setOpacity(0.8); - settings.layerRouteMarker = new OpenLayers.Layer.Markers( - 'Route markers'); - settings.map.addLayer(settings.layerRouteMarker); - settings.layerRouteMarker.setOpacity(0.8); - } }, // end of init // zoom in from the map menu @@ -266,7 +269,7 @@ See the file COPYING for details. * Display menu on the map */ displayMapMenu: function(e) { - helpers.hidePopup(); + if (helpers.hidePopup()) return; if ($('#chimere_map_menu').is(":visible")){ $('#chimere_map_menu').hide(); } else{ @@ -445,7 +448,6 @@ See the file COPYING for details. if (settings.current_popup == feature.popup) { feature.popup.hide(); if (!settings.simple){ - $('#panel').removeClass('panel-minified'); $('#detail').hide(); } } else { @@ -505,23 +507,51 @@ See the file COPYING for details. settings.current_feature.geometry = linestring; settings.layerVectors.addFeatures([settings.current_feature]); }, + routingInputChange: function(){ + $('#map_menu_clear').show(); + if ($('#nominatim_start_lon').val()){ + settings.routing_start = new OpenLayers.Marker( + new OpenLayers.LonLat($('#nominatim_start_lon').val(), + $('#nominatim_start_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + } + if ($('#nominatim_end_lon').val()){ + settings.routing_end = new OpenLayers.Marker( + new OpenLayers.LonLat($('#nominatim_end_lon').val(), + $('#nominatim_end_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + } + if (settings.routing_end && settings.routing_start) methods.route(); + }, + // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); 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(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); settings.routing_steps.push(new OpenLayers.Marker( settings.current_position.clone(), settings.icon_step.clone())); @@ -533,20 +563,36 @@ See the file COPYING for details. // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); 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(''); $('#chimere_map_menu').hide(); $('#map_menu_clear').hide(); - $('#chimere_itinerary_panel').dialog('close'); + $('#chimere_itinerary').hide(); + $('#chimere_itinerary_form').show(); settings.layerRoute.removeAllFeatures(); settings.layerRouteMarker.clearMarkers(); settings.routing_start = null; @@ -566,6 +612,8 @@ See the file COPYING for details. steps.push(settings.routing_end.lonlat.clone()); // create the appropriate URL var uri = extra_url + "route/" + var transport = $('input:radio[name=transport]:checked').val(); + uri += transport + "/" for (var i = 0; i < steps.length; i++) { var step = steps[i].transform( settings.map.getProjectionObject(), @@ -582,8 +630,13 @@ See the file COPYING for details. for (var i = 0; i < data.features.length; i++) { methods.putRoute(data.features[i]); } - $('#chimere_itinerary').html( + settings.map.zoomToExtent( + settings.layerRoute.getDataExtent()); + settings.map.zoomOut(); + $('#chimere_itinerary_content').html( data.properties.description); + $('#chimere_itinerary').show(); + $('#chimere_itinerary_form').hide(); $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { @@ -630,7 +683,6 @@ See the file COPYING for details. } else { if (!settings.simple) { - $('#panel').addClass('panel-minified'); $('#detail').html(data).show(); } else { @@ -803,13 +855,16 @@ See the file COPYING for details. 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(); + return true; + } } } + return false; }, getSubcategories: function (category_id) { if(settings.get_subcategories_fx) { @@ -934,8 +989,22 @@ See the file COPYING for details. 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 + }, + success: function (data) { + vals = $.parseJSON(data); + $('#nominatim_'+response_id).html(vals.display_name); + $('#chimere_'+response_id).html(vals.display_name); + } + }); } - }; // End of helpers $.fn.chimere = function (thing) { diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js new file mode 100644 index 0000000..fea654d --- /dev/null +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -0,0 +1,41 @@ + +$(function(){ + $(".nominatim-widget").autocomplete({ + source: function (request, response) { + $.ajax({ + url: nominatim_url, + data: { + format: "json", + q: request.term, + }, + success: function ( data ) { + response ( $.map( $.parseJSON(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(''); + jQuery("#map").chimere("routingInputChange"); + return false; + }, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } + }); +}); diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html index 226480b..4948a1c 100644 --- a/chimere/templates/chimere/blocks/routing.html +++ b/chimere/templates/chimere/blocks/routing.html @@ -1,8 +1,35 @@ {% load i18n %} {% if routing %} +{{itinerary_form.media}} {% trans "Itinerary"%}
+
+ {% for hidden in itinerary_form.hidden_fields %} + {{ hidden }} + {% endfor %} + {% for field in itinerary_form.visible_fields %} + {% if field.label %}

{%endif%} +

{{field}}

+ {% endfor %} +
+ +
+ {% trans "Start:"%}
+
+
+
+ {% trans "Finish:"%} +
{% endif%} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 51e64bf..946e769 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -118,7 +118,8 @@ def map_menu(context): @register.inclusion_tag('chimere/blocks/routing.html', takes_context=True) def routing(context): - context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} + context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING, + 'itinerary_form':context['itinerary_form']} return context_data @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) diff --git a/chimere/urls.py b/chimere/urls.py index aec82fb..81263a0 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -54,9 +54,11 @@ if settings.CHIMERE_FEEDS: if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ + r'(?P(%s))/' r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ r'(?P([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ - r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$' % + ('|'.join([key for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])), 'route', name="route"), ) diff --git a/chimere/views.py b/chimere/views.py index 308fb14..bd1f441 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -48,7 +48,7 @@ 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 from chimere.route import router @@ -122,6 +122,8 @@ 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 settings.CHIMERE_ENABLE_ROUTING: + response_dct['itinerary_form'] = RoutingForm() response_dct.update({ 'actions':actions, 'action_selected':('view',), 'error_message':'', diff --git a/chimere/widgets.py b/chimere/widgets.py index da2bc54..f5617de 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -26,6 +26,9 @@ from django.core.exceptions import ObjectDoesNotExist from django.conf import settings from django.contrib.gis.db import models from django.contrib.gis.geos import fromstr +from django.utils.html import conditional_escape +from django.forms.widgets import RadioInput, RadioFieldRenderer +from django.utils.encoding import force_unicode from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ @@ -100,6 +103,41 @@ class ChosenSelectWidget(forms.Select): u"\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 %s' % (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 = "
\n" % kwargs['attrs']['id'] + rendered += super(ButtonSelectWidget, self).render(*args, **kwargs) + rendered += u"\n\n
\n" % kwargs['attrs']['id'] + return mark_safe(rendered) + class TextareaWidget(forms.Textarea): """ Manage the edition of a text using TinyMCE @@ -121,6 +159,21 @@ class DatePickerWidget(forms.TextInput): u"\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""" + + + + + +""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL} + return mark_safe(tpl) + class PointChooserWidget(forms.TextInput): """ Manage the edition of point on a map diff --git a/example_project/settings.py b/example_project/settings.py index ead2c93..46b8e95 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -5,6 +5,7 @@ # overload all theses settings in your local_settings.py file import os +_ = lambda s: s DEBUG = False TEMPLATE_DEBUG = DEBUG @@ -77,6 +78,17 @@ CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' # 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', @@ -84,6 +96,8 @@ CHIMERE_ROUTING_ENGINE = { 'DB_PATH': '/var/local/routino/', } +NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search' + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From d63c56a5f8350c61117efec402b3ae67cc4c5a9b Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 14 Aug 2012 18:29:38 +0200 Subject: Routing & UI improvment: first work on map menu * add a map menu on the main interface * add a new templatetag: map_menu * add CHIMERE_ENABLE_ROUTING to settings * add a routing settings (boolean) in jquery.chimere.js * manage zoomin, zoomout, center in jquery.chimere.js --- chimere/static/chimere/css/styles.css | 23 ++++++++++++ chimere/static/chimere/js/jquery.chimere.js | 48 +++++++++++++++++++++++++- chimere/templates/chimere/blocks/map_menu.html | 12 +++++++ chimere/templates/chimere/main_map.html | 1 + chimere/templatetags/chimere_tags.py | 5 +++ example_project/settings.py | 3 ++ 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 chimere/templates/chimere/blocks/map_menu.html diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 71ca07b..66f2be5 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -413,6 +413,29 @@ ul#share li{ padding-top:0; } +#chimere_map_menu{ + z-index:4; + display:none; + position:absolute; + padding:0.5em; + background-color:#fff; + border:1px solid #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +#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; +} + .simple #panel{ top:5px; } diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 40f5ee2..1c2a973 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -81,6 +81,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { units: 'm', projection: new OpenLayers.Projection('EPSG:4326'), theme:null, + routing: false, // enable routing management 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 @@ -119,6 +120,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); @@ -211,7 +214,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { methods.loadGeoObjects(); // Hide popUp when clicking on map settings.map.events.register('click', settings.map, - helpers.hidePopup); + methods.displayMapMenu); } else { if (!settings.edition_type_is_route){ map.events.register('click', settings.map, @@ -223,8 +226,50 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.layerVectors, helpers.featureRouteCreated); } } + $('#chimere_map_menu #map_menu_zoomin').bind("click", + methods.zoomIn); + $('#chimere_map_menu #map_menu_zoomout').bind("click", + methods.zoomOut); + $('#map_menu_center').bind("click", methods.mapCenter); }, // end of init + // zoom in from the map 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); + }, + + /* + * Display menu on the map + */ + displayMapMenu: function(e) { + helpers.hidePopup(); + if ($('#chimere_map_menu').is(":visible")){ + $('#chimere_map_menu').hide(); + } else{ + settings.current_position = + 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 */ @@ -383,6 +428,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } else { + $('#chimere_map_menu').hide(); // Default popup if (feature.popup && feature.popup.visible()) { if (settings.current_popup == feature.popup) { diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html new file mode 100644 index 0000000..513d6ba --- /dev/null +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -0,0 +1,12 @@ +{% load i18n %} +
+
    + {% if routing %} +
  • {% trans "From" context "routing" %}
  • +
  • {% trans "To" context "routing" %}
  • + {% endif%} +
  • {% trans "Zoom in" %}
  • +
  • {% trans "Zoom out" %}
  • +
  • {% trans "Center the map here" %}
  • +
+
diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index f84b372..ae6578f 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -34,6 +34,7 @@ + {% map_menu %} {% map_params %} {% endblock %} {% block footer %} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index e7f7248..70dabaa 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -111,6 +111,11 @@ def head_chimere(context): } 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} + return context_data + @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) def map_params(context): context_data = {} diff --git a/example_project/settings.py b/example_project/settings.py index 38bc916..448da80 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -75,6 +75,9 @@ CHIMERE_OSM_PASSWORD = 'test' # encoding for shapefile import CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' +# enable routing in Chimère +CHIMERE_ENABLE_ROUTING = False + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From 1feeb42a1f12811106764ef8203bfe1a10362fb8 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 01:38:28 +0200 Subject: First working version of routing. * add an utilitary Routing class to manage different routing system * implement the routing with routino * add a view to manage routes * itinerary panel template * JS management of routing: * manage flag markers on the map * request the route when start and finish flag are set * display the route and the itinerary description * add of two flags images * itinerary panel CSS * french translation update --- chimere/locale/fr/LC_MESSAGES/django.po | 42 ++++++++-- chimere/route.py | 87 +++++++++++++++++++ chimere/static/chimere/css/styles.css | 47 +++++++++-- chimere/static/chimere/img/flag-finish.png | Bin 0 -> 1652 bytes chimere/static/chimere/img/flag-start.png | Bin 0 -> 1165 bytes chimere/static/chimere/img/images_licences | 7 ++ chimere/static/chimere/js/jquery.chimere.js | 102 ++++++++++++++++++++++- chimere/templates/chimere/blocks/map_menu.html | 8 ++ chimere/templates/chimere/blocks/map_params.html | 1 + chimere/templatetags/chimere_tags.py | 2 + chimere/urls.py | 8 ++ chimere/views.py | 21 +++++ example_project/settings.py | 7 ++ 13 files changed, 312 insertions(+), 20 deletions(-) create mode 100644 chimere/route.py create mode 100644 chimere/static/chimere/img/flag-finish.png create mode 100644 chimere/static/chimere/img/flag-start.png diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index 4462ff1..f9874fd 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-20 21:17+0200\n" +"POT-Creation-Date: 2012-08-22 01:59+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" @@ -630,19 +630,19 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:229 +#: views.py:234 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:312 +#: views.py:317 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:434 +#: views.py:439 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:437 +#: views.py:442 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." @@ -651,15 +651,15 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:441 +#: views.py:446 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:572 +#: views.py:577 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:679 +#: views.py:702 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" @@ -913,6 +913,32 @@ msgstr "Ce site utilise Chimère" msgid "Map" msgstr "Carte" +#: templates/chimere/blocks/map_menu.html:5 +msgctxt "routing" +msgid "From" +msgstr "En partir" + +#: templates/chimere/blocks/map_menu.html:6 +msgctxt "routing" +msgid "To" +msgstr "Y aller" + +#: templates/chimere/blocks/map_menu.html:8 +msgid "Zoom in" +msgstr "Zoomer en avant" + +#: templates/chimere/blocks/map_menu.html:9 +msgid "Zoom out" +msgstr "Zoomer en arrière" + +#: templates/chimere/blocks/map_menu.html:10 +msgid "Center the map here" +msgstr "Centrer la carte ici" + +#: templates/chimere/blocks/map_menu.html:16 +msgid "Itinerary" +msgstr "Itinéraire" + #: templates/chimere/blocks/map_params.html:6 msgid "Permalink" msgstr "Lien permanent" diff --git a/chimere/route.py b/chimere/route.py new file mode 100644 index 0000000..efc6763 --- /dev/null +++ b/chimere/route.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 Étienne Loks +# + +# 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 . + +# 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.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(""), re.compile(""), + re.compile("")] + def route(self, lon1, lat1, lon2, lat2, session_id='', transport='foot'): + ''' + 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, + "--lat2=%0.15f" % lat2, + "--lon2=%0.15f" % lon2 + ] + tmp_dir = tempfile.mkdtemp(prefix='chimere_') + os.sep + p = Popen(args, stdout=PIPE, cwd=tmp_dir) + p.communicate() + ds = DataSource(tmp_dir + 'shortest-track.gpx') + if not ds: + return [], 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()) + desc.append('
') + desc = BeautifulSoup('\n'.join(desc)).prettify() + shutil.rmtree(tmp_dir) + return res, desc +router = None +if settings.CHIMERE_ROUTING_ENGINE['ENGINE'] == 'routino': + router = RoutinoRouter() + diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 66f2be5..61dcc4e 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -15,7 +15,8 @@ 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, +#chimere_itinerary td.l{ color:#fff; } @@ -29,7 +30,10 @@ h2, h3, th, .action li, .action li a, body, h2, h3, th, .ui-widget-header, -.action li.selected, #no-js-message{ +.action li.selected, #no-js-message, +#content .olControlLayerSwitcher .layersDiv, +#content .olControlLayerSwitcher span, +#chimere_itinerary td.l{ background-color:#449506; } @@ -38,7 +42,7 @@ body, h2, h3, th, } fieldset, .action li, #content, -#map-footer, #panel, #areas, +#map-footer, #panel, #chimere_itinerary_panel, #areas, #welcome, #detail, .detail_footer a, #content .olControlLayerSwitcher .layersDiv, #content .olControlLayerSwitcher span, @@ -63,7 +67,7 @@ div.warning, #content, .action li.selected, #content .olControlLayerSwitcher .layersDiv, -#panel, #map-footer, +#panel, #map-footer, #chimere_itinerary_panel, #utils-div{ border:1px solid #327e04; } @@ -79,7 +83,7 @@ div.warning, opacity:0.9; } -#panel, #areas, #detail, #category_detail{ +#panel, #areas, #detail, #category_detail, #chimere_itinerary_panel{ opacity:0.8; } @@ -413,6 +417,33 @@ ul#share li{ padding-top:0; } +#chimere_itinerary_panel{ + position:absolute; + z-index:5; + top:50px; + left:50px; + width:300px; + padding:0.5em; + padding-top:0; + display:none; +} + +#chimere_itinerary{ + height:250px; + overflow:auto; + padding:0.2em 1em; + font-size:0.9em; +} + +#chimere_itinerary td.l{ + padding:6px; +} + +#chimere_itinerary span.j{ + font-style:italic; +} + + #chimere_map_menu{ z-index:4; display:none; @@ -420,9 +451,9 @@ ul#share li{ padding:0.5em; background-color:#fff; border:1px solid #bbb; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + -webkit-border-radius: 0 8px 8px 8px; + -moz-border-radius: 0 8px 8px 8px; + border-radius: 0 8px 8px 8px; } #chimere_map_menu ul, #chimere_map_menu li{ diff --git a/chimere/static/chimere/img/flag-finish.png b/chimere/static/chimere/img/flag-finish.png new file mode 100644 index 0000000..04bfa1d Binary files /dev/null and b/chimere/static/chimere/img/flag-finish.png differ diff --git a/chimere/static/chimere/img/flag-start.png b/chimere/static/chimere/img/flag-start.png new file mode 100644 index 0000000..c93f2a3 Binary files /dev/null and b/chimere/static/chimere/img/flag-start.png differ diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 0e732fc..000fdf0 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -30,3 +30,10 @@ Url 2: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg Author: Sbrools Licence: Public domain Url: https://commons.wikimedia.org/wiki/File:8thNote.svg + +* Flags image credit (flag-start.png, flag-finish.png) + +Author: FatCow Web Hosting +Licence: Creative Commons Attribution 3.0 United States license +Url: https://upload.wikimedia.org/wikipedia/commons/6/64/Farm-Fresh_flag_finish.png + https://upload.wikimedia.org/wikipedia/commons/c/cb/Farm-Fresh_flag_1.png diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 1c2a973..3ffb1f9 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -226,11 +226,30 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.layerVectors, helpers.featureRouteCreated); } } - $('#chimere_map_menu #map_menu_zoomin').bind("click", - methods.zoomIn); - $('#chimere_map_menu #map_menu_zoomout').bind("click", - methods.zoomOut); + $('#map_menu_zoomin').bind("click", methods.zoomIn); + $('#map_menu_zoomout').bind("click", methods.zoomOut); $('#map_menu_center').bind("click", methods.mapCenter); + if (settings.routing){ + settings.routing_start = null; + settings.routing_end = null; + settings.icon_start = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-start.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_end = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-finish.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + $('#map_menu_from').bind("click", methods.routingFrom); + $('#map_menu_to').bind("click", methods.routingTo); + settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); + settings.map.addLayer(settings.layerRoute); + settings.layerRoute.setOpacity(0.8); + settings.layerRouteMarker = new OpenLayers.Layer.Markers( + 'Route markers'); + settings.map.addLayer(settings.layerRouteMarker); + settings.layerRouteMarker.setOpacity(0.8); + } }, // end of init // zoom in from the map menu @@ -494,6 +513,81 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.current_feature.geometry = linestring; settings.layerVectors.addFeatures([settings.current_feature]); }, + // set the start point for routing + routingFrom: function(){ + $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').hide(); + settings.routing_start = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + if (settings.routing_end) methods.route(); + }, + + // set the finish point for routing + routingTo: function(){ + $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').hide(); + settings.routing_end = new OpenLayers.Marker( + settings.current_position.clone(), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + if (settings.routing_start) methods.route(); + }, + + // display a route + route: function(){ + if (!settings.routing_start || !settings.routing_end){ + return; + } + var start = settings.routing_start.lonlat.clone().transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + var end = settings.routing_end.lonlat.clone().transform( + settings.map.getProjectionObject(), + EPSG_DISPLAY_PROJECTION); + var uri = extra_url + "route/" + + start.lon + '_' + + start.lat + '_' + + end.lon + '_' + + end.lat; + $.ajax({url: uri, + dataType: "json", + success: function (data) { + settings.layerRoute.removeAllFeatures(); + for (var i = 0; i < data.features.length; i++) { + methods.putRoute(data.features[i]); + } + $('#chimere_itinerary').html( + data.properties.description); + $('#chimere_itinerary_panel').show(); + }, + error: function (data) { + settings.layerRoute.removeAllFeatures(); + } + }); + + }, + /* + Put a route on the map + */ + putRoute: function(polyline) { + var point_array = new Array(); + for (i=0; i{% trans "Center the map here" %} + +{% if routing %} +
+

{% trans "Itinerary" %}

+
+
+
+{% endif%} diff --git a/chimere/templates/chimere/blocks/map_params.html b/chimere/templates/chimere/blocks/map_params.html index c8f97eb..1afd722 100644 --- a/chimere/templates/chimere/blocks/map_params.html +++ b/chimere/templates/chimere/blocks/map_params.html @@ -5,6 +5,7 @@ chimere_init_options["map_layers"] = [{{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}}); diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 70dabaa..5256518 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -123,6 +123,8 @@ def map_params(context): 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 settings.CHIMERE_ENABLE_ROUTING \ + else 'none' 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) diff --git a/chimere/urls.py b/chimere/urls.py index a232382..ad88e32 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -51,6 +51,14 @@ if settings.CHIMERE_FEEDS: LatestPOIsByZoneID(), name='feeds-areaid'), ) +if settings.CHIMERE_ENABLE_ROUTING: + urlpatterns += patterns('chimere.views', + url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', + 'route', name="route"), + ) + urlpatterns += patterns('chimere.views', url(r'^charte/?$', 'charte', name="charte"), url(r'^(?P[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', name="contact"), diff --git a/chimere/views.py b/chimere/views.py index f61e209..ad4b0ca 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -26,6 +26,7 @@ Views of the project import datetime from itertools import groupby +import simplejson from django.conf import settings from django.core import serializers @@ -49,6 +50,8 @@ from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \ FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\ notifyStaff, AreaForm +from chimere.route import router + def get_base_uri(request): base_uri = 'http://' if 'HTTP_REFERER' in request.META: @@ -635,6 +638,24 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return redir return HttpResponseRedirect(response_dct['extra_url'] + parameters) +def route(request, area_name, lon1, lat1, lon2, lat2, transport='foot'): + ''' + Get the JSON for a route + ''' + try: + lon1, lat1 = float(lon1), float(lat1) + lon2, lat2 = float(lon2), float(lat2) + except ValueError: + return HttpResponse('no results') + jsons, desc = router.route(lon1, lat1, lon2, lat2, transport=transport, + session_id=request.session.session_key) + if not jsons: + return HttpResponse('no results') + jsonencoder = simplejson.JSONEncoder() + data = '{"properties":{"description":%s}, "type": "FeatureCollection",'\ + '"features":[%s]}' % (jsonencoder.encode(desc), ",".join(jsons)) + return HttpResponse(data) + def rss(request, area_name=''): ''' Redirect to RSS subscription page diff --git a/example_project/settings.py b/example_project/settings.py index 448da80..5684386 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -78,6 +78,13 @@ CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' # enable routing in Chimère CHIMERE_ENABLE_ROUTING = False +# available routing engine: 'routino' +CHIMERE_ROUTING_ENGINE = { + 'ENGINE': 'routino', + 'PATH': '/usr/local/src/web/bin/router', + 'DB_PATH': '/var/local/routino/', +} + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From cbcb67f2b92f7348a81406efd1d8bb6d7d2fbd31 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 17:28:38 +0200 Subject: Minor changes on routing presentation --- chimere/route.py | 4 ++-- chimere/static/chimere/css/styles.css | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/chimere/route.py b/chimere/route.py index efc6763..207232b 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -72,12 +72,12 @@ class RoutinoRouter(Router): res = [] for multiline in multilines: res += [geom.geojson for geom in multiline] - desc = [''] + 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()) - desc.append('
') + desc = [''] + desc[1:-2] + [desc[-1], '
'] desc = BeautifulSoup('\n'.join(desc)).prettify() shutil.rmtree(tmp_dir) return res, desc diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 61dcc4e..58a7944 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -436,13 +436,19 @@ ul#share li{ } #chimere_itinerary td.l{ - padding:6px; + padding:5px; + width:55px; } #chimere_itinerary span.j{ font-style:italic; } +#chimere_itinerary span.t, +#chimere_itinerary span.b +{ + text-transform: lowercase; +} #chimere_map_menu{ z-index:4; -- cgit v1.2.3 From d1834d853739383585f2ad0a99afb606c1f16978 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 18:41:43 +0200 Subject: Use JQuery UI dialog for itinerary detail --- chimere/static/chimere/css/styles.css | 20 +------------------- chimere/static/chimere/js/jquery.chimere.js | 9 ++++++--- chimere/templates/chimere/blocks/map_menu.html | 13 +++++++++++-- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 58a7944..5fd9cd7 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -417,27 +417,9 @@ ul#share li{ padding-top:0; } -#chimere_itinerary_panel{ - position:absolute; - z-index:5; - top:50px; - left:50px; - width:300px; - padding:0.5em; - padding-top:0; - display:none; -} - -#chimere_itinerary{ - height:250px; - overflow:auto; - padding:0.2em 1em; - font-size:0.9em; -} - #chimere_itinerary td.l{ padding:5px; - width:55px; + width:60px; } #chimere_itinerary span.j{ diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 3ffb1f9..4639a09 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -516,7 +516,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').hide(); + //$('#chimere_itinerary_panel').hide(); + $('#chimere_itinerary_panel').dialog('close'); settings.routing_start = new OpenLayers.Marker( settings.current_position.clone(), settings.icon_start); @@ -527,7 +528,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').hide(); + //$('#chimere_itinerary_panel').hide(); + $('#chimere_itinerary_panel').dialog('close'); settings.routing_end = new OpenLayers.Marker( settings.current_position.clone(), settings.icon_end); @@ -560,7 +562,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } $('#chimere_itinerary').html( data.properties.description); - $('#chimere_itinerary_panel').show(); + //$('#chimere_itinerary_panel').show(); + $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { settings.layerRoute.removeAllFeatures(); diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index 4c78a5b..52a4107 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -12,9 +12,18 @@ {% if routing %} -
-

{% trans "Itinerary" %}

+
+ {% endif%} -- cgit v1.2.3 From c107a69ca98f5be7893cbe2a03e84cfaae1b9ca9 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:10:57 +0200 Subject: Improve routing: manage steps * Manage steps in routing core * Add extra parameters for steps in urls.py * Modify the view to parse steps and send them to the routing core * Manage steps in JS (add many step flags and send a correct request to the view) * Manage a clear itinerary action in JS * Add a new flag image for steps * CSS improvement --- chimere/route.py | 12 +++-- chimere/static/chimere/css/styles.css | 21 +++++++++ chimere/static/chimere/img/flag-step.png | Bin 0 -> 1256 bytes chimere/static/chimere/img/images_licences | 7 +-- chimere/static/chimere/js/jquery.chimere.js | 62 +++++++++++++++++++------ chimere/templates/chimere/blocks/map_menu.html | 2 + chimere/urls.py | 1 + chimere/views.py | 10 ++-- 8 files changed, 93 insertions(+), 22 deletions(-) create mode 100644 chimere/static/chimere/img/flag-step.png diff --git a/chimere/route.py b/chimere/route.py index 207232b..bc08a39 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -39,7 +39,7 @@ class Router: class RoutinoRouter(Router): re_desc = [re.compile(""), re.compile(""), re.compile("")] - def route(self, lon1, lat1, lon2, lat2, session_id='', transport='foot'): + def route(self, lon1, lat1, lon2, lat2, steps=[], transport='foot'): ''' Get a list of geojson polylines and route description ''' @@ -53,9 +53,15 @@ class RoutinoRouter(Router): "--output-gpx-track", "--lat1=%0.15f" % lat1, "--lon1=%0.15f" % lon1, - "--lat2=%0.15f" % lat2, - "--lon2=%0.15f" % lon2 ] + 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() diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 5fd9cd7..9133001 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -417,11 +417,24 @@ ul#share li{ padding-top:0; } +#chimere_itinerary table +{ + border-collapse:collapse; +} + +#chimere_itinerary td{ + border:8px solid #fff; +} + #chimere_itinerary td.l{ padding:5px; width:60px; } +#chimere_itinerary td.r{ + font-size:0.8em; +} + #chimere_itinerary span.j{ font-style:italic; } @@ -444,6 +457,14 @@ ul#share li{ 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; diff --git a/chimere/static/chimere/img/flag-step.png b/chimere/static/chimere/img/flag-step.png new file mode 100644 index 0000000..5556c94 Binary files /dev/null and b/chimere/static/chimere/img/flag-step.png differ diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 000fdf0..03d63dc 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -31,9 +31,10 @@ Author: Sbrools Licence: Public domain Url: https://commons.wikimedia.org/wiki/File:8thNote.svg -* Flags image credit (flag-start.png, flag-finish.png) +* 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/6/64/Farm-Fresh_flag_finish.png - https://upload.wikimedia.org/wikipedia/commons/c/cb/Farm-Fresh_flag_1.png +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/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 4639a09..7676517 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -231,17 +231,24 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { $('#map_menu_center').bind("click", methods.mapCenter); if (settings.routing){ settings.routing_start = null; + settings.routing_steps = new Array(); settings.routing_end = null; settings.icon_start = new OpenLayers.Icon( STATIC_URL + "chimere/img/flag-start.png", new OpenLayers.Size(32, 32), new OpenLayers.Pixel(0, -32)); + settings.icon_step = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-step.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); settings.icon_end = new OpenLayers.Icon( STATIC_URL + "chimere/img/flag-finish.png", new OpenLayers.Size(32, 32), new OpenLayers.Pixel(0, -32)); $('#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.layerRoute.setOpacity(0.8); @@ -516,7 +523,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); - //$('#chimere_itinerary_panel').hide(); + $('#map_menu_clear').show(); $('#chimere_itinerary_panel').dialog('close'); settings.routing_start = new OpenLayers.Marker( settings.current_position.clone(), @@ -525,10 +532,23 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (settings.routing_end) methods.route(); }, + // add a step point for routing + routingAddStep: function(){ + $('#chimere_map_menu').hide(); + $('#map_menu_clear').show(); + $('#chimere_itinerary_panel').dialog('close'); + 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 (settings.routing_end && settings.routing_start) methods.route(); + }, + // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); - //$('#chimere_itinerary_panel').hide(); + $('#map_menu_clear').show(); $('#chimere_itinerary_panel').dialog('close'); settings.routing_end = new OpenLayers.Marker( settings.current_position.clone(), @@ -537,22 +557,39 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (settings.routing_start) methods.route(); }, + // clear the current itinerary + routingClear: function(){ + $('#chimere_map_menu').hide(); + $('#map_menu_clear').hide(); + $('#chimere_itinerary_panel').dialog('close'); + settings.layerRoute.removeAllFeatures(); + settings.layerRouteMarker.clearMarkers(); + settings.routing_start = null; + settings.routing_end = null; + settings.routing_steps = new Array(); + }, + // display a route route: function(){ if (!settings.routing_start || !settings.routing_end){ return; } - var start = settings.routing_start.lonlat.clone().transform( - settings.map.getProjectionObject(), - EPSG_DISPLAY_PROJECTION); - var end = settings.routing_end.lonlat.clone().transform( + 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/" + for (var i = 0; i < steps.length; i++) { + var step = steps[i].transform( settings.map.getProjectionObject(), EPSG_DISPLAY_PROJECTION); - var uri = extra_url + "route/" - + start.lon + '_' - + start.lat + '_' - + end.lon + '_' - + end.lat; + if (i > 0){ + uri += '_'; + } + uri += step.lon + '_' + step.lat; + } $.ajax({url: uri, dataType: "json", success: function (data) { @@ -562,8 +599,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } $('#chimere_itinerary').html( data.properties.description); - //$('#chimere_itinerary_panel').show(); - $('#chimere_itinerary_panel').dialog('open'); + $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { settings.layerRoute.removeAllFeatures(); diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index 52a4107..e541c1e 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -3,7 +3,9 @@
    {% if routing %}
  • {% trans "From" context "routing" %}
  • +
  • {% trans "Add a step" context "routing" %}
  • {% trans "To" context "routing" %}
  • +
  • {% trans "Clear the itinerary" context "routing" %}
  • {% endif%}
  • {% trans "Zoom in" %}
  • {% trans "Zoom out" %}
  • diff --git a/chimere/urls.py b/chimere/urls.py index ad88e32..aec82fb 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -55,6 +55,7 @@ if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ + r'(?P([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', 'route', name="route"), ) diff --git a/chimere/views.py b/chimere/views.py index ad4b0ca..df403e0 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -638,17 +638,21 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return redir return HttpResponseRedirect(response_dct['extra_url'] + parameters) -def route(request, area_name, lon1, lat1, lon2, lat2, transport='foot'): +def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, + transport='foot'): ''' 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 = router.route(lon1, lat1, lon2, lat2, transport=transport, - session_id=request.session.session_key) + jsons, desc = router.route(lon1, lat1, lon2, lat2, steps=steps, + transport=transport) if not jsons: return HttpResponse('no results') jsonencoder = simplejson.JSONEncoder() -- cgit v1.2.3 From 0d31e5541ec10834d6762bc66fba80aa9a440e51 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:27:37 +0200 Subject: Improve itinerary layout * create a proper templatetag for routing * add a button to show the routing dialog * some cleaning in the css file --- chimere/static/chimere/css/styles.css | 14 +++----------- chimere/templates/chimere/blocks/map_menu.html | 17 ----------------- chimere/templates/chimere/blocks/routing.html | 21 +++++++++++++++++++++ chimere/templates/chimere/main_map.html | 1 + chimere/templatetags/chimere_tags.py | 5 +++++ 5 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 chimere/templates/chimere/blocks/routing.html diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 9133001..dec91e6 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -594,26 +594,18 @@ p.warning{ } -#welcome_button, +a#welcome_button, +a#routing_button, #permalink{ display: block; - text-align:center; margin:0.3em; padding:0.2em; -} - -a#welcome_button, -#permalink{ + width:100%; font-size:14px; text-align:center; text-decoration:none; } -#welcome_button, -#permalink{ - width:100%; -} - /* forms */ table.inline-table{ diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html index e541c1e..38fb4a8 100644 --- a/chimere/templates/chimere/blocks/map_menu.html +++ b/chimere/templates/chimere/blocks/map_menu.html @@ -12,20 +12,3 @@
  • {% trans "Center the map here" %}
- -{% if routing %} -
-
-
-
- -{% endif%} diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html new file mode 100644 index 0000000..226480b --- /dev/null +++ b/chimere/templates/chimere/blocks/routing.html @@ -0,0 +1,21 @@ +{% load i18n %} +{% if routing %} +{% trans "Itinerary"%} +
+
+
+
+ +{% endif%} diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index ae6578f..8cb7da3 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -22,6 +22,7 @@ {% if areas_visible %} {% display_areas %} {% endif %} + {% routing %} {% display_news news_visible %} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 5256518..51e64bf 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -116,6 +116,11 @@ def map_menu(context): context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} return context_data +@register.inclusion_tag('chimere/blocks/routing.html', takes_context=True) +def routing(context): + context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} + return context_data + @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) def map_params(context): context_data = {} -- cgit v1.2.3 From 232a1de132fa75431b45c008b72dafbcc6130b14 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 15 Aug 2012 20:30:59 +0200 Subject: Update french translation with routing --- chimere/locale/fr/LC_MESSAGES/django.po | 47 ++++++++++++--------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index f9874fd..ad397ae 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -920,25 +920,31 @@ 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:9 +#: templates/chimere/blocks/map_menu.html:11 msgid "Zoom out" msgstr "Zoomer en arrière" -#: templates/chimere/blocks/map_menu.html:10 +#: templates/chimere/blocks/map_menu.html:12 msgid "Center the map here" msgstr "Centrer la carte ici" -#: templates/chimere/blocks/map_menu.html:16 -msgid "Itinerary" -msgstr "Itinéraire" - #: templates/chimere/blocks/map_params.html:6 msgid "Permalink" msgstr "Lien permanent" @@ -949,6 +955,11 @@ msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." +#: templates/chimere/blocks/routing.html:3 +#: templates/chimere/blocks/routing.html:13 +msgid "Itinerary" +msgstr "Itinéraire" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -1012,27 +1023,3 @@ msgstr "Choisir une zone pré-définie" #: templates/chimere/feeds/rss.html:64 msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" - -#~ msgid "Submit a modification" -#~ msgstr "Proposer une modification" - -#~ msgid "Add/modify a site" -#~ msgstr "Ajouter ou modifier un site" - -#~ msgid "Categorys" -#~ msgstr "Catégories" - -#~ msgid "Theme" -#~ msgstr "Thème" - -#~ msgid "Subtheme" -#~ msgstr "Sous-thème" - -#~ msgid "Subthemes" -#~ msgstr "Sous-thèmes" - -#~ msgid "Themes" -#~ msgstr "Thèmes" - -#~ msgid "Site name" -#~ msgstr "Nom du site" -- cgit v1.2.3 From 1091d481584af4662488ee83d7fa1421f8d1700c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 17 Aug 2012 13:13:15 +0200 Subject: Improve routing interface and functionalities * fix POI clicking * create a nominatim widget to get coordinates from text * create a JQuery UI button select widget * create a routing form to get itinerary from a textual form * CSS for the routing form * Reverse nominatim: when a point is get for routing on the map label for this point is get from nominatim * Add transport management by user choice * Update french translation --- chimere/forms.py | 18 ++- chimere/locale/fr/LC_MESSAGES/django.po | 87 ++++++++++----- chimere/static/chimere/css/styles.css | 58 ++++++++-- chimere/static/chimere/img/images_licences | 6 +- chimere/static/chimere/js/jquery.chimere.js | 155 +++++++++++++++++++------- chimere/static/chimere/js/nominatim-widget.js | 41 +++++++ chimere/templates/chimere/blocks/routing.html | 37 +++++- chimere/templatetags/chimere_tags.py | 3 +- chimere/urls.py | 4 +- chimere/views.py | 4 +- chimere/widgets.py | 53 +++++++++ example_project/settings.py | 14 +++ 12 files changed, 392 insertions(+), 88 deletions(-) create mode 100644 chimere/static/chimere/js/nominatim-widget.js diff --git a/chimere/forms.py b/chimere/forms.py index d877a22..f49a903 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -35,7 +35,7 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ PictureFile, Importer from chimere.widgets import AreaField, PointField, TextareaWidget, \ - DatePickerWidget + DatePickerWidget, ButtonSelectWidget, NominatimWidget from datetime import timedelta, datetime, tzinfo @@ -454,3 +454,19 @@ class AreaForm(AreaAdminForm): class Meta: model = Area +class RoutingForm(forms.Form): + transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, + choices=settings.CHIMERE_ROUTING_TRANSPORT, + initial=settings.CHIMERE_ROUTING_TRANSPORT[0][0]) + 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) + + def __init__(self, *args, **kwargs): + super(RoutingForm, self).__init__(*args, **kwargs) + if not settings.CHIMERE_ROUTING_SPEEDS: + self.fields.pop('speed') + 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 ad397ae..e68d0e8 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -134,8 +134,20 @@ msgstr "Nom" msgid "Area" msgstr "Zone" -#: models.py:50 models.py:124 models.py:151 models.py:244 models.py:453 -#: models.py:822 models.py:903 +#: forms.py:445 +msgid "Start" +msgstr "Départ" + +#: forms.py:446 +msgid "Finish" +msgstr "Arrivée :" + +#: forms.py:447 +msgid "Speed" +msgstr "Vitesse" + +#: models.py:49 models.py:123 models.py:150 models.py:241 models.py:441 +#: models.py:810 models.py:891 msgid "Available" msgstr "Disponible" @@ -630,19 +642,19 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:234 +#: views.py:228 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:317 +#: views.py:307 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:439 +#: views.py:429 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:442 +#: views.py:432 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." @@ -663,36 +675,36 @@ msgstr "Pas de catégorie disponible sur cette zone." msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:187 +#: widgets.py:240 msgid "Latitude" msgstr "Latitude" -#: widgets.py:187 +#: widgets.py:240 msgid "Longitude" msgstr "Longitude" -#: widgets.py:212 +#: widgets.py:265 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:262 +#: widgets.py:315 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:263 +#: widgets.py:316 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:265 +#: widgets.py:318 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:266 +#: widgets.py:319 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:267 +#: widgets.py:320 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -700,7 +712,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:269 +#: widgets.py:322 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -708,17 +720,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:274 +#: widgets.py:327 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:275 +#: widgets.py:328 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:276 +#: widgets.py:329 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -726,7 +738,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:278 +#: widgets.py:331 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -735,33 +747,33 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:285 +#: widgets.py:338 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:288 +#: widgets.py:341 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:289 +#: widgets.py:342 msgid "or" msgstr "ou" -#: widgets.py:294 +#: widgets.py:347 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:317 +#: widgets.py:370 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:317 +#: widgets.py:370 msgid "Draw" msgstr "Tracer" -#: widgets.py:442 +#: widgets.py:495 msgid "Select..." msgstr "Sélectionner..." @@ -955,11 +967,27 @@ msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." -#: templates/chimere/blocks/routing.html:3 -#: templates/chimere/blocks/routing.html:13 +#: templates/chimere/blocks/routing.html:4 +#: templates/chimere/blocks/routing.html:40 msgid "Itinerary" msgstr "Itinéraire" +#: templates/chimere/blocks/routing.html:19 +msgid "Modify" +msgstr "Modifier" + +#: templates/chimere/blocks/routing.html:22 +msgid "New search" +msgstr "Nouvelle recherche" + +#: templates/chimere/blocks/routing.html:27 +msgid "Start:" +msgstr "Départ :" + +#: templates/chimere/blocks/routing.html:31 +msgid "Finish:" +msgstr "Arrivée :" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -1023,3 +1051,6 @@ msgstr "Choisir une zone pré-définie" #: templates/chimere/feeds/rss.html:64 msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" + +#~ msgid "End" +#~ msgstr "Fin" diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index dec91e6..ceb3b60 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -411,36 +411,69 @@ ul#share li{ top:50px; right:18px; width:300px; - bottom:44px; + max-height:300px; overflow:auto; padding:0.5em; padding-top:0; } -#chimere_itinerary table +#chimere_itinerary_panel, +#chimere_itinerary{ + display:none; +} + +#chimere_itinerary_panel label{ + color:#000; +} + +#chimere_itinerary_panel p +{ + margin:0.5em; +} + +.itinerary_label{ + font-size:0.9em; + padding-top:0.5em; + font-style:italic; +} + +.itinerary_label.label{ + font-style:normal; + font-weight:bold; +} + + +#chimere_itinerary_content{ + overflow:auto; + height:190px; + margin-top:10px; +} + +#chimere_itinerary_content table { border-collapse:collapse; } -#chimere_itinerary td{ - border:8px solid #fff; +#chimere_itinerary_content table td{ + border:1px solid #333; } -#chimere_itinerary td.l{ +#chimere_itinerary_content td.l{ padding:5px; width:60px; } -#chimere_itinerary td.r{ +#chimere_itinerary_content td.r{ font-size:0.8em; + padding:0.8em; } -#chimere_itinerary span.j{ +#chimere_itinerary_content span.j{ font-style:italic; } -#chimere_itinerary span.t, -#chimere_itinerary span.b +#chimere_itinerary_content span.t, +#chimere_itinerary_content span.b { text-transform: lowercase; } @@ -476,6 +509,13 @@ ul#share li{ background-color:#ccc; } +.nominatim-label{ + display:block; + font-size:0.9em; + font-weight:bold; + height:2.8em; +} + .simple #panel{ top:5px; } diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 03d63dc..cbc9307 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,7 +16,7 @@ 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 @@ -24,7 +24,7 @@ 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 -* Quaver image credit +* Quaver image credit (8thNote.png) * An 8th-note. Author: Sbrools diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 7676517..ff90f28 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -171,6 +171,40 @@ 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; + settings.icon_start = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-start.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_step = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-step.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + settings.icon_end = new OpenLayers.Icon( + STATIC_URL + "chimere/img/flag-finish.png", + new OpenLayers.Size(32, 32), + new OpenLayers.Pixel(0, -32)); + $('#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.layerRoute.setOpacity(0.8); + settings.layerRouteMarker = new OpenLayers.Layer.Markers( + 'Route markers'); + settings.map.addLayer(settings.layerRouteMarker); + settings.layerRouteMarker.setOpacity(0.8); + } /* Vectors layer */ settings.layerVectors = new OpenLayers.Layer.Vector("Vector Layer"); settings.map.addLayer(settings.layerVectors); @@ -226,37 +260,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.layerVectors, helpers.featureRouteCreated); } } - $('#map_menu_zoomin').bind("click", methods.zoomIn); - $('#map_menu_zoomout').bind("click", methods.zoomOut); - $('#map_menu_center').bind("click", methods.mapCenter); - if (settings.routing){ - settings.routing_start = null; - settings.routing_steps = new Array(); - settings.routing_end = null; - settings.icon_start = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-start.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - settings.icon_step = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-step.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - settings.icon_end = new OpenLayers.Icon( - STATIC_URL + "chimere/img/flag-finish.png", - new OpenLayers.Size(32, 32), - new OpenLayers.Pixel(0, -32)); - $('#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.layerRoute.setOpacity(0.8); - settings.layerRouteMarker = new OpenLayers.Layer.Markers( - 'Route markers'); - settings.map.addLayer(settings.layerRouteMarker); - settings.layerRouteMarker.setOpacity(0.8); - } }, // end of init // zoom in from the map menu @@ -281,7 +284,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { * Display menu on the map */ displayMapMenu: function(e) { - helpers.hidePopup(); + if (helpers.hidePopup()) return; if ($('#chimere_map_menu').is(":visible")){ $('#chimere_map_menu').hide(); } else{ @@ -460,7 +463,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if (settings.current_popup == feature.popup) { feature.popup.hide(); if (!settings.simple){ - $('#panel').removeClass('panel-minified'); $('#detail').hide(); } } else { @@ -520,23 +522,51 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.current_feature.geometry = linestring; settings.layerVectors.addFeatures([settings.current_feature]); }, + routingInputChange: function(){ + $('#map_menu_clear').show(); + if ($('#nominatim_start_lon').val()){ + settings.routing_start = new OpenLayers.Marker( + new OpenLayers.LonLat($('#nominatim_start_lon').val(), + $('#nominatim_start_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_start); + settings.layerRouteMarker.addMarker(settings.routing_start); + } + if ($('#nominatim_end_lon').val()){ + settings.routing_end = new OpenLayers.Marker( + new OpenLayers.LonLat($('#nominatim_end_lon').val(), + $('#nominatim_end_lat').val() + ).transform(EPSG_DISPLAY_PROJECTION, + settings.map.getProjectionObject()), + settings.icon_end); + settings.layerRouteMarker.addMarker(settings.routing_end); + } + if (settings.routing_end && settings.routing_start) methods.route(); + }, + // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); 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(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); settings.routing_steps.push(new OpenLayers.Marker( settings.current_position.clone(), settings.icon_step.clone())); @@ -548,20 +578,36 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); + $('#chimere_itinerary_panel').dialog('open'); $('#map_menu_clear').show(); - $('#chimere_itinerary_panel').dialog('close'); 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(''); $('#chimere_map_menu').hide(); $('#map_menu_clear').hide(); - $('#chimere_itinerary_panel').dialog('close'); + $('#chimere_itinerary').hide(); + $('#chimere_itinerary_form').show(); settings.layerRoute.removeAllFeatures(); settings.layerRouteMarker.clearMarkers(); settings.routing_start = null; @@ -581,6 +627,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { steps.push(settings.routing_end.lonlat.clone()); // create the appropriate URL var uri = extra_url + "route/" + var transport = $('input:radio[name=transport]:checked').val(); + uri += transport + "/" for (var i = 0; i < steps.length; i++) { var step = steps[i].transform( settings.map.getProjectionObject(), @@ -597,8 +645,13 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { for (var i = 0; i < data.features.length; i++) { methods.putRoute(data.features[i]); } - $('#chimere_itinerary').html( + settings.map.zoomToExtent( + settings.layerRoute.getDataExtent()); + settings.map.zoomOut(); + $('#chimere_itinerary_content').html( data.properties.description); + $('#chimere_itinerary').show(); + $('#chimere_itinerary_form').hide(); $('#chimere_itinerary_panel').dialog('open'); }, error: function (data) { @@ -645,7 +698,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } else { if (!settings.simple) { - $('#panel').addClass('panel-minified'); $('#detail').html(data).show(); } else { @@ -818,13 +870,16 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { 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(); + return true; + } } } + return false; }, getSubcategories: function (category_id) { if(settings.get_subcategories_fx) { @@ -949,8 +1004,22 @@ 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 + }, + success: function (data) { + vals = $.parseJSON(data); + $('#nominatim_'+response_id).html(vals.display_name); + $('#chimere_'+response_id).html(vals.display_name); + } + }); } - }; // End of helpers $.fn.chimere = function (thing) { diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js new file mode 100644 index 0000000..fea654d --- /dev/null +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -0,0 +1,41 @@ + +$(function(){ + $(".nominatim-widget").autocomplete({ + source: function (request, response) { + $.ajax({ + url: nominatim_url, + data: { + format: "json", + q: request.term, + }, + success: function ( data ) { + response ( $.map( $.parseJSON(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(''); + jQuery("#map").chimere("routingInputChange"); + return false; + }, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } + }); +}); diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html index 226480b..4948a1c 100644 --- a/chimere/templates/chimere/blocks/routing.html +++ b/chimere/templates/chimere/blocks/routing.html @@ -1,8 +1,35 @@ {% load i18n %} {% if routing %} +{{itinerary_form.media}} {% trans "Itinerary"%}
+
+ {% for hidden in itinerary_form.hidden_fields %} + {{ hidden }} + {% endfor %} + {% for field in itinerary_form.visible_fields %} + {% if field.label %}

{%endif%} +

{{field}}

+ {% endfor %} +
+ +
+ {% trans "Start:"%}
+
+
+
+ {% trans "Finish:"%} +
{% endif%} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 51e64bf..946e769 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -118,7 +118,8 @@ def map_menu(context): @register.inclusion_tag('chimere/blocks/routing.html', takes_context=True) def routing(context): - context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING} + context_data = {'routing':settings.CHIMERE_ENABLE_ROUTING, + 'itinerary_form':context['itinerary_form']} return context_data @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) diff --git a/chimere/urls.py b/chimere/urls.py index aec82fb..81263a0 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -54,9 +54,11 @@ if settings.CHIMERE_FEEDS: if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ + r'(?P(%s))/' r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ r'(?P([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ - r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$', + r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$' % + ('|'.join([key for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])), 'route', name="route"), ) diff --git a/chimere/views.py b/chimere/views.py index df403e0..dd3f89a 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -48,7 +48,7 @@ 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 from chimere.route import router @@ -122,6 +122,8 @@ 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 settings.CHIMERE_ENABLE_ROUTING: + response_dct['itinerary_form'] = RoutingForm() response_dct.update({ 'actions':actions, 'action_selected':('view',), 'error_message':'', diff --git a/chimere/widgets.py b/chimere/widgets.py index 8e2b8ad..b520fcd 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -26,6 +26,9 @@ from django.core.exceptions import ObjectDoesNotExist from django.conf import settings from django.contrib.gis.db import models from django.contrib.gis.geos import fromstr +from django.utils.html import conditional_escape +from django.forms.widgets import RadioInput, RadioFieldRenderer +from django.utils.encoding import force_unicode from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ @@ -100,6 +103,41 @@ class ChosenSelectWidget(forms.Select): u"\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 %s' % (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 = "
\n" % kwargs['attrs']['id'] + rendered += super(ButtonSelectWidget, self).render(*args, **kwargs) + rendered += u"\n\n
\n" % kwargs['attrs']['id'] + return mark_safe(rendered) + class TextareaWidget(forms.Textarea): """ Manage the edition of a text using TinyMCE @@ -121,6 +159,21 @@ class DatePickerWidget(forms.TextInput): u"\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""" + + + + + +""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL} + return mark_safe(tpl) + class PointChooserWidget(forms.TextInput): """ Manage the edition of point on a map diff --git a/example_project/settings.py b/example_project/settings.py index 5684386..750d798 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -5,6 +5,7 @@ # overload all theses settings in your local_settings.py file import os +_ = lambda s: s DEBUG = False TEMPLATE_DEBUG = DEBUG @@ -78,6 +79,17 @@ CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' # 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', @@ -85,6 +97,8 @@ CHIMERE_ROUTING_ENGINE = { 'DB_PATH': '/var/local/routino/', } +NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search' + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From e76025c3123a07ec828d805719256e6dcc68a025 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 23 Aug 2012 17:51:47 +0200 Subject: Minor formating --- chimere/templates/base.html | 36 +++++++-------- chimere/templates/chimere/blocks/categories.html | 56 ++++++++++++------------ 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/chimere/templates/base.html b/chimere/templates/base.html index 2a50fc3..149cc71 100644 --- a/chimere/templates/base.html +++ b/chimere/templates/base.html @@ -7,25 +7,25 @@ {% endblock %} - {% block extrabody %} +{% block extrabody %} +{% endblock %} +{% block body %} + + +
+ {% block content %} + {% endblock %} +
+ +{% endblock %} diff --git a/chimere/templates/chimere/blocks/categories.html b/chimere/templates/chimere/blocks/categories.html index 5ba89fc..9c5ffd6 100644 --- a/chimere/templates/chimere/blocks/categories.html +++ b/chimere/templates/chimere/blocks/categories.html @@ -1,29 +1,29 @@ {% load i18n %} -
    - {% for category, lst_sub_categories in sub_categories %} -
  • - control - - {% trans category.name %} - {% trans "Zoom to" %} {{category.name}} - -
  • - {% endfor %} -
  • - {% trans "Display markers and routes waiting for validation"%} -
  • -
+
    + {% for category, lst_sub_categories in sub_categories %} +
  • + control + + {% trans category.name %} + {% trans "Zoom to" %} {{category.name}} + +
  • + {% endfor %} +
  • + {% trans "Display markers and routes waiting for validation"%} +
  • +
-- cgit v1.2.3 From 64264c7792d8a34016312c88f195fe9530ba8c0e Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 23 Aug 2012 23:42:25 +0200 Subject: JS: add a selected class to main categories --- chimere/static/chimere/js/jquery.chimere.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index bb24d2e..d148a8e 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -363,7 +363,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 > label"); + 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){ -- cgit v1.2.3 From c76f9631a14e21881329f4f1383d2fd3327d432d Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 24 Aug 2012 12:01:13 +0200 Subject: JS: allow custom windows opening function fro routing --- chimere/static/chimere/js/jquery.chimere.js | 34 +++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index d148a8e..c1d028c 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -77,11 +77,15 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { controls:[new OpenLayers.Control.Navigation(), new OpenLayers.Control.SimplePanZoom(), new OpenLayers.Control.ScaleLine()], + category_accordion: true, // category opening behave like an accordion maxResolution: 156543.0399, units: 'm', projection: new OpenLayers.Projection('EPSG:4326'), theme:null, 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 @@ -284,7 +288,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { * Display menu on the map */ displayMapMenu: function(e) { - if (helpers.hidePopup()) return; + if (methods.hidePopup()) return; if ($('#chimere_map_menu').is(":visible")){ $('#chimere_map_menu').hide(); } else{ @@ -377,6 +381,14 @@ 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 () { @@ -554,7 +566,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the start point for routing routingFrom: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').dialog('open'); + settings.routing_panel_open(); $('#map_menu_clear').show(); settings.routing_start = new OpenLayers.Marker( settings.current_position.clone(), @@ -571,7 +583,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // add a step point for routing routingAddStep: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').dialog('open'); + settings.routing_panel_open(); $('#map_menu_clear').show(); settings.routing_steps.push(new OpenLayers.Marker( settings.current_position.clone(), @@ -584,7 +596,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // set the finish point for routing routingTo: function(){ $('#chimere_map_menu').hide(); - $('#chimere_itinerary_panel').dialog('open'); + settings.routing_panel_open(); $('#map_menu_clear').show(); settings.routing_end = new OpenLayers.Marker( settings.current_position.clone(), @@ -658,7 +670,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { data.properties.description); $('#chimere_itinerary').show(); $('#chimere_itinerary_form').hide(); - $('#chimere_itinerary_panel').dialog('open'); + settings.routing_panel_open(); }, error: function (data) { settings.layerRoute.removeAllFeatures(); @@ -745,9 +757,11 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { // Check if element is currently visible or not var was_visible = $("#maincategory_" + id).is(":visible"); // Close all categories - $("#categories ul.subcategories").hide(); + if (settings.category_accordion){ + $("#categories ul.subcategories").hide(); + $("#categories img.toggle_category").attr("src", STATIC_URL + "chimere/img/plus.png"); + } // Put a minus image - $("#categories img.toggle_category").attr("src", STATIC_URL + "chimere/img/plus.png"); if (!was_visible) { // Show the subcategories @@ -756,6 +770,12 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { $("#maincategory_img_" + id).attr("src", STATIC_URL + "chimere/img/minus.png"); settings.current_category = id; } + if (!settings.category_accordion && was_visible) + { + $("#maincategory_" + id).toggle(); + // Put a minus image + $("#maincategory_img_" + id).attr("src", STATIC_URL + "chimere/img/plus.png"); + } }, zoomToCurrentExtent: function(){ /* zoom to current extent */ -- cgit v1.2.3 From 77c4e8a2e20ace72a88bcada608be89dd588f49a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 25 Aug 2012 03:17:56 +0200 Subject: Improvement in route display and parsing --- chimere/route.py | 25 +++++++++++--- chimere/static/chimere/css/styles.css | 47 +++++++++++++++------------ chimere/static/chimere/js/jquery.chimere.js | 11 +++++-- chimere/static/chimere/js/nominatim-widget.js | 7 ++-- chimere/templates/chimere/blocks/routing.html | 8 +++++ chimere/views.py | 11 ++++--- chimere/widgets.py | 10 ++++-- 7 files changed, 84 insertions(+), 35 deletions(-) diff --git a/chimere/route.py b/chimere/route.py index bc08a39..9c8b59c 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -67,7 +67,7 @@ class RoutinoRouter(Router): p.communicate() ds = DataSource(tmp_dir + 'shortest-track.gpx') if not ds: - return [], None + return [], None, None layer = ds[0] trk_layer = None for layer in ds: @@ -83,10 +83,27 @@ class RoutinoRouter(Router): 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()) - desc = [''] + desc[1:-2] + [desc[-1], '
'] - desc = BeautifulSoup('\n'.join(desc)).prettify() + total = self.webify(desc[-1]) + desc = desc[1:-2] + # very fragile piece of code but only break the numerotation + number_tpl = '%d.' + desc = [re.sub('', 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 + return res, desc, total + + @staticmethod + def webify(lbl): + lbl = re.sub("", "", lbl) + lbl = re.sub("", "", lbl) + lbl = re.sub("

{%endif%}

{{field}}

{% endfor %} + {% trans "Search" %}
@@ -23,6 +24,9 @@
+
+ +
{% trans "Start:"%}
@@ -41,6 +45,7 @@ $(document).ready(function() { height: 360, resizable: false }); + $('#search_routing').button({'disabled':true}); $('#routing_button').click(function(){ $('#chimere_itinerary_panel').dialog('open'); }); @@ -51,6 +56,9 @@ $(document).ready(function() { $('#chimere_itinerary_new').click(function(){ $('#map').chimere('routingClear'); }); + $('#search_routing').click(function(){ + $('#map').chimere('route'); + }); }); {% endif%} diff --git a/chimere/views.py b/chimere/views.py index c71b4eb..c8097a1 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -653,13 +653,16 @@ def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, steps = [(steps[i*2], steps[i*2+1]) for i in range(len(steps)/2)] except ValueError: return HttpResponse('no results') - jsons, desc = router.route(lon1, lat1, lon2, lat2, steps=steps, - transport=transport) + jsons, desc, total = router.route(lon1, lat1, lon2, lat2, steps=steps, + transport=transport) if not jsons: return HttpResponse('no results') jsonencoder = simplejson.JSONEncoder() - data = '{"properties":{"description":%s}, "type": "FeatureCollection",'\ - '"features":[%s]}' % (jsonencoder.encode(desc), ",".join(jsons)) + total = jsonencoder.encode(total) + desc = jsonencoder.encode(desc) + data = '{"properties":{"total":%s, "description":%s}, '\ + '"type": "FeatureCollection", "features":[%s]}' % (total, desc, + ",".join(jsons)) return HttpResponse(data) def rss(request, area_name=''): diff --git a/chimere/widgets.py b/chimere/widgets.py index b520fcd..23095c7 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -166,12 +166,18 @@ class NominatimWidget(forms.TextInput): tpl = u""" - + -""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL} +""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL, + 'label':_(u"Street, City, Country")} return mark_safe(tpl) class PointChooserWidget(forms.TextInput): -- cgit v1.2.3 From 095e0ac0304e90f2e07a23b745571c781005920c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 25 Aug 2012 15:26:36 +0200 Subject: JS: allow custom popup class --- chimere/static/chimere/js/jquery.chimere.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 6e0fa25..12fb68f 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -77,6 +77,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { controls:[new OpenLayers.Control.Navigation(), new OpenLayers.Control.SimplePanZoom(), new OpenLayers.Control.ScaleLine()], + popupClass: OpenLayers.Popup.FramedCloud, category_accordion: true, // category opening behave like an accordion maxResolution: 156543.0399, units: 'm', @@ -445,7 +446,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { EPSG_PROJECTION), {icon:iconclone}); feature.pk = mark.properties.pk; - feature.popupClass = OpenLayers.Popup.FramedCloud; + feature.popupClass = settings.popupClass; feature.data.popupContentHTML = "
"; feature.data.popupContentHTML += mark.properties.name; feature.data.popupContentHTML += "
"; -- cgit v1.2.3 From 0ee09412bff460d70894e9b11ed3a90481a74608 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 26 Aug 2012 14:10:54 +0200 Subject: Improve detail display * add a short_description property to marker which cut desc * add options in jquery.chimere.js to customize popup display --- chimere/models.py | 24 ++++++++++++++++++++++ chimere/static/chimere/css/styles.css | 3 --- chimere/static/chimere/js/jquery.chimere.js | 21 +++++++++++++++---- .../templates/chimere/blocks/multimedia_file.html | 2 +- example_project/settings.py | 3 +++ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/chimere/models.py b/chimere/models.py index 4f6d4e0..8bff588 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,6 +25,7 @@ import simplejson as json from lxml import etree from PIL import Image from subprocess import Popen, PIPE +from BeautifulSoup import BeautifulSoup from django.conf import settings from django.contrib.gis.db import models @@ -344,6 +345,29 @@ class Marker(GeographicItem): if settings.CHIMERE_DAYS_BEFORE_EVENT: return self.start_date + @property + def description_short(self): + if not self.description: + return '' + if len(self.description) <= settings.CHIMERE_SHORT_DESC_LENGTH: + return self.description + desc = self.description[: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 + short_desc += "..." + return BeautifulSoup(short_desc).prettify() + class Meta: ordering = ('status', 'name') verbose_name = _(u"Point of interest") diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index ecdd70c..640fc29 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -367,8 +367,6 @@ ul#share li{ #main-map{ position:absolute; - margin:0px; - padding:0px; height:93%; margin:0; padding:0; @@ -697,7 +695,6 @@ table.inline-table td input[type=file]{ margin-right: auto; } - /* openlayer customisation */ .olControlPermalink { display: block; diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 12fb68f..4bc487e 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -74,15 +74,18 @@ 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.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, routing: false, // enable routing management routing_panel_open: function(){ $('#chimere_itinerary_panel').dialog('open'); @@ -454,6 +457,14 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { var marker = feature.createMarker(); /* manage markers events */ var _popup = function() { + if (settings.popupContentFull){ + var pixel = new OpenLayers.Pixel(0, 60); + var lonlat = map.getLonLatFromPixel(pixel); + lonlat.lon = settings.current_feature.lonlat.lon; + settings.map.setCenter(lonlat); + } else { + methods.center_on_feature(); + } /* show the popup */ if (settings.current_popup != null) { settings.current_popup.hide(); @@ -466,7 +477,9 @@ 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 markerClick = function (evt) { @@ -716,14 +729,14 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { var params = {} if (settings.simple) { params["simple"] = 1; } $.ajax({url: uri, - data: params, + data: params, success: function (data) { if ( settings.display_feature_detail_fx ) { // Custom function ? settings.display_feature_detail_fx(data, settings); } else { - if (!settings.simple) { + if (!settings.popupContentFull) { $('#detail').html(data).show(); } else { diff --git a/chimere/templates/chimere/blocks/multimedia_file.html b/chimere/templates/chimere/blocks/multimedia_file.html index a1e9868..d659348 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 %} -{{multimedia_item.name}}{% endif %} +{{multimedia_item.name}}{% endif %} {% if multimedia_item.url %} {% if multimedia_item.multimedia_type.iframe %} diff --git a/example_project/settings.py b/example_project/settings.py index e78751d..2aef8be 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -100,6 +100,9 @@ NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search' CHIMERE_THUMBS_SCALE_HEIGHT=250 CHIMERE_THUMBS_SCALE_WIDTH=None +# length of short description +CHIMERE_SHORT_DESC_LENGTH = 400 + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) -- cgit v1.2.3 From 2c42264e87b32b9ddd73d66bfc0e6ccffcba7b41 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 26 Aug 2012 17:10:22 +0200 Subject: Add the possibility to submit a modification by email --- chimere/forms.py | 9 +- chimere/locale/fr/LC_MESSAGES/django.po | 320 +++++++++++++++------------- chimere/static/chimere/css/styles.css | 8 +- chimere/static/chimere/img/feed.png | Bin 0 -> 1453 bytes chimere/static/chimere/js/jquery.chimere.js | 3 +- chimere/templates/chimere/detail.html | 3 +- chimere/views.py | 7 +- example_project/settings.py | 2 + 8 files changed, 197 insertions(+), 155 deletions(-) create mode 100644 chimere/static/chimere/img/feed.png diff --git a/chimere/forms.py b/chimere/forms.py index 20171df..0b74b32 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -53,13 +53,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 diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index b986cf5..787005b 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,18 +7,18 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-22 14:54+0200\n" +"POT-Creation-Date: 2012-08-26 17:07+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:8 models.py:502 +#: __init__.py:8 models.py:526 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: __init__.py:9 models.py:551 +#: __init__.py:9 models.py:583 msgid "Picture files" msgstr "Fichiers d'image" @@ -86,394 +86,406 @@ 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:76 +#: forms.py:81 msgid "New submission for" msgstr "Nouvelle proposition pour" -#: forms.py:77 +#: forms.py:82 #, 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:79 +#: forms.py:84 msgid "To valid, precise or unvalid this item: " msgstr "Pour valider, préciser ou rejeter cet élément : " -#: forms.py:89 +#: forms.py:94 msgid "Email (optional)" msgstr "Courriel (optionnel) " -#: forms.py:90 +#: forms.py:95 msgid "Object" msgstr "Objet" -#: forms.py:158 +#: forms.py:163 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:171 +#: forms.py:174 msgid "This field is mandatory for the selected categories" msgstr "Ce champ est obligatoire pour les catégories sélectionnées" -#: forms.py:385 +#: forms.py:388 msgid "File" msgstr "Fichier" -#: forms.py:391 +#: forms.py:394 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:396 models.py:49 models.py:102 models.py:123 models.py:136 -#: models.py:150 models.py:233 models.py:449 models.py:492 models.py:536 -#: models.py:567 models.py:804 models.py:816 models.py:901 +#: forms.py:399 models.py:50 models.py:103 models.py:124 models.py:137 +#: models.py:151 models.py:234 models.py:473 models.py:516 models.py:560 +#: models.py:643 models.py:881 models.py:893 models.py:978 #: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 msgid "Name" msgstr "Nom" -#: forms.py:405 models.py:853 +#: forms.py:408 models.py:930 msgid "Area" msgstr "Zone" -#: forms.py:461 +#: forms.py:464 msgid "Start" msgstr "Départ" -#: forms.py:462 +#: forms.py:465 msgid "Finish" msgstr "Arrivée :" -#: forms.py:463 +#: forms.py:466 msgid "Speed" msgstr "Vitesse" -#: models.py:50 models.py:124 models.py:151 models.py:244 models.py:453 -#: models.py:822 models.py:903 +#: models.py:51 models.py:125 models.py:152 models.py:245 models.py:477 +#: models.py:899 models.py:980 msgid "Available" msgstr "Disponible" -#: models.py:51 models.py:912 +#: models.py:52 models.py:989 msgid "Date" msgstr "Date" -#: models.py:57 models.py:58 +#: models.py:58 models.py:59 msgid "News" msgstr "Nouvelle" -#: models.py:63 +#: models.py:64 msgid "Parameters" msgstr "Paramètres" -#: models.py:67 +#: models.py:68 msgid "TinyUrl" msgstr "Mini-url" -#: models.py:106 models.py:113 models.py:153 +#: models.py:107 models.py:114 models.py:154 msgid "Color theme" msgstr "Thème de couleur" -#: models.py:111 +#: models.py:112 msgid "Code" msgstr "Code" -#: models.py:112 models.py:125 models.py:155 models.py:494 models.py:543 -#: models.py:821 models.py:890 models.py:902 +#: models.py:113 models.py:126 models.py:156 models.py:518 models.py:575 +#: models.py:898 models.py:967 models.py:979 msgid "Order" msgstr "Ordre" -#: models.py:118 +#: models.py:119 msgid "Color" msgstr "Couleur" -#: models.py:131 models.py:149 templates/chimere/main_map.html:13 +#: models.py:132 models.py:150 templates/chimere/main_map.html:13 msgid "Category" msgstr "Catégorie" -#: models.py:137 models.py:445 models.py:537 models.py:632 +#: models.py:138 models.py:469 models.py:561 models.py:708 msgid "Image" msgstr "Image" -#: models.py:139 models.py:539 models.py:634 +#: models.py:140 models.py:563 models.py:710 msgid "Height" msgstr "Hauteur" -#: models.py:140 models.py:540 models.py:635 +#: models.py:141 models.py:564 models.py:711 msgid "Width" msgstr "Largeur" -#: models.py:144 models.py:152 +#: models.py:145 models.py:153 msgid "Icon" msgstr "Icône" -#: models.py:156 +#: models.py:157 msgid "Marker" msgstr "Point d'intérêt" -#: models.py:157 models.py:628 models.py:643 +#: models.py:158 models.py:704 models.py:719 #: templates/chimere/edit_route.html:27 msgid "Route" msgstr "Trajet" -#: models.py:158 +#: models.py:159 msgid "Both" msgstr "Mixte" -#: models.py:159 +#: models.py:160 msgid "Item type" msgstr "Type d'élément" -#: models.py:164 +#: models.py:165 msgid "Sub-category" msgstr "Sous-catégorie" -#: models.py:165 +#: models.py:166 msgid "Sub-categories" msgstr "Sous-catégories" -#: models.py:211 +#: models.py:212 msgid "Importer type" msgstr "Type d'import" -#: models.py:214 models.py:255 +#: models.py:215 models.py:256 msgid "Source" msgstr "Source" -#: models.py:216 +#: models.py:217 msgid "Filter" msgstr "Filtre" -#: models.py:219 +#: models.py:220 msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:220 +#: models.py:221 msgid "State" msgstr "État" -#: models.py:222 +#: models.py:223 msgid "SRID" msgstr "SRID" -#: models.py:223 +#: models.py:224 msgid "Zipped file" msgstr "Fichier zippé" -#: models.py:226 +#: models.py:227 msgid "Importer" msgstr "Import" -#: models.py:235 +#: models.py:236 msgid "Submitter session key" msgstr "Clé de session du demandeur" -#: models.py:237 +#: models.py:238 msgid "Submitter name or nickname" msgstr "Nom ou pseudo du demandeur" -#: models.py:239 +#: models.py:240 msgid "Submitter email" msgstr "Courriel du demandeur" -#: models.py:241 +#: models.py:242 msgid "Submitter comment" msgstr "Commentaire du demandeur" -#: models.py:243 +#: models.py:244 msgid "Submited" msgstr "Soumis" -#: models.py:245 +#: models.py:246 msgid "Modified" msgstr "Modifié" -#: models.py:246 +#: models.py:247 msgid "Disabled" msgstr "Désactivé" -#: models.py:247 +#: models.py:248 msgid "Imported" msgstr "Importé" -#: models.py:248 +#: models.py:249 msgid "Excluded" msgstr "Exclu" -#: models.py:250 +#: models.py:251 msgid "Status" msgstr "État" -#: models.py:251 +#: models.py:252 msgid "Import key" msgstr "Clé d'import" -#: models.py:253 +#: models.py:254 msgid "Import version" msgstr "Version de l'import" -#: models.py:258 templates/chimere/edit.html:56 +#: models.py:259 templates/chimere/edit.html:56 #: templates/chimere/edit_route.html:52 msgid "Start date" msgstr "Date de début" -#: models.py:259 +#: models.py:260 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:261 templates/chimere/edit.html:62 +#: models.py:262 templates/chimere/edit.html:62 #: templates/chimere/edit_route.html:58 msgid "End date" msgstr "Date de fin" -#: models.py:262 +#: models.py:263 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:294 +#: models.py:295 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:295 +#: models.py:296 msgid "Localisation" msgstr "Localisation" -#: models.py:297 +#: models.py:298 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:301 templates/chimere/edit.html:49 +#: models.py:302 templates/chimere/edit.html:49 #: templates/chimere/edit_route.html:46 msgid "Description" msgstr "Description" -#: models.py:349 models.py:932 +#: models.py:373 models.py:1009 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:443 +#: models.py:467 msgid "Audio" msgstr "Audio" -#: models.py:444 +#: models.py:468 msgid "Video" msgstr "Vidéo" -#: models.py:446 +#: models.py:470 msgid "Other" msgstr "Autre" -#: models.py:447 +#: models.py:471 msgid "Media type" msgstr "Type de media" -#: models.py:450 +#: models.py:474 msgid "Mime type" msgstr "Type mime" -#: models.py:452 +#: models.py:476 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:456 +#: models.py:480 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:457 +#: models.py:481 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:493 +#: models.py:517 msgid "Url" msgstr "Url" -#: models.py:496 models.py:541 +#: models.py:520 models.py:565 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:501 +#: models.py:525 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:550 +#: models.py:567 +msgid "Thumbnail" +msgstr "Miniature" + +#: models.py:571 +msgid "Thumbnail height" +msgstr "Hauteur de la miniature" + +#: models.py:573 +msgid "Thumbnail width" +msgstr "Largeur de la miniature" + +#: models.py:582 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:568 +#: models.py:644 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:569 +#: models.py:645 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:571 +#: models.py:647 msgid "KML" msgstr "KML" -#: models.py:571 +#: models.py:647 msgid "GPX" msgstr "GPX" -#: models.py:576 +#: models.py:652 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:577 +#: models.py:653 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:627 +#: models.py:703 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:631 +#: models.py:707 msgid "Associated file" msgstr "Fichier associé" -#: models.py:805 +#: models.py:882 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:811 +#: models.py:888 msgid "Layer" msgstr "Couche" -#: models.py:817 +#: models.py:894 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:819 templates/chimere/blocks/welcome.html:3 +#: models.py:896 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:823 +#: models.py:900 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:825 +#: models.py:902 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:827 +#: models.py:904 msgid "Default area" msgstr "Zone par défaut" -#: models.py:828 +#: models.py:905 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:832 +#: models.py:909 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:834 +#: models.py:911 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:835 +#: models.py:912 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -481,68 +493,68 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:839 models.py:906 +#: models.py:916 models.py:983 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:840 +#: models.py:917 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:842 +#: models.py:919 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:844 +#: models.py:921 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:891 +#: models.py:968 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:895 models.py:896 +#: models.py:972 models.py:973 msgid "Layers" msgstr "Couches" -#: models.py:904 +#: models.py:981 msgid "Mandatory" msgstr "Obligatoire" -#: models.py:907 +#: models.py:984 msgid "" "If no sub-category is set all the property applies to all sub-categories" msgstr "" "Si aucune sous-catégorie n'est précisée, cette propriété est disponible pour " "toutes les sous-catégories" -#: models.py:909 +#: models.py:986 msgid "Text" msgstr "Texte" -#: models.py:910 +#: models.py:987 msgid "Long text" msgstr "Texte long" -#: models.py:911 +#: models.py:988 msgid "Password" msgstr "Mot de passe" -#: models.py:917 +#: models.py:994 msgid "Type" msgstr "Type" -#: models.py:922 models.py:934 +#: models.py:999 models.py:1011 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:935 +#: models.py:1012 msgid "Value" msgstr "Valeur" -#: models.py:939 +#: models.py:1016 msgid "Property" msgstr "Propriété" @@ -642,7 +654,7 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:236 +#: views.py:237 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." @@ -667,44 +679,48 @@ msgstr "" msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:579 +#: views.py:584 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:708 +#: views.py:716 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:240 +#: widgets.py:180 +msgid "Street, City, Country" +msgstr "Rue, Commune, Pays" + +#: widgets.py:246 msgid "Latitude" msgstr "Latitude" -#: widgets.py:240 +#: widgets.py:246 msgid "Longitude" msgstr "Longitude" -#: widgets.py:265 +#: widgets.py:271 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:315 +#: widgets.py:321 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:316 +#: widgets.py:322 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:318 +#: widgets.py:324 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:319 +#: widgets.py:325 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:320 +#: widgets.py:326 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -712,7 +728,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:322 +#: widgets.py:328 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -720,17 +736,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:327 +#: widgets.py:333 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:328 +#: widgets.py:334 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:329 +#: widgets.py:335 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -738,7 +754,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:331 +#: widgets.py:337 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -747,33 +763,33 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:338 +#: widgets.py:344 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:341 +#: widgets.py:347 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:342 +#: widgets.py:348 msgid "or" msgstr "ou" -#: widgets.py:347 +#: widgets.py:353 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:370 +#: widgets.py:376 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:370 +#: widgets.py:376 msgid "Draw" msgstr "Tracer" -#: widgets.py:495 +#: widgets.py:501 msgid "Select..." msgstr "Sélectionner..." @@ -821,6 +837,10 @@ msgstr "Partager sur" msgid "Share" msgstr "Partager" +#: templates/chimere/detail.html:36 +msgid "Propose a modification" +msgstr "Proposer une modification" + #: templates/chimere/edit.html:20 msgid "Error" msgstr "Erreur" @@ -870,7 +890,11 @@ msgstr "Votre courriel" msgid "Comments about your submission" msgstr "Commentaires au sujet de votre proposition" -#: templates/chimere/edit.html:133 templates/chimere/edit_route.html:77 +#: templates/chimere/edit.html:134 +msgid "Upload in progress. Please wait..." +msgstr "Traitement en cours. Veuillez patienter..." + +#: templates/chimere/edit.html:151 templates/chimere/edit_route.html:77 msgid "Propose" msgstr "Proposez" @@ -957,7 +981,7 @@ msgstr "Zoomer en arrière" msgid "Center the map here" msgstr "Centrer la carte ici" -#: templates/chimere/blocks/map_params.html:6 +#: templates/chimere/blocks/map_params.html:8 msgid "Permalink" msgstr "Lien permanent" @@ -968,23 +992,27 @@ msgstr "" "libre Flash." #: templates/chimere/blocks/routing.html:4 -#: templates/chimere/blocks/routing.html:40 +#: templates/chimere/blocks/routing.html:44 msgid "Itinerary" msgstr "Itinéraire" -#: templates/chimere/blocks/routing.html:19 +#: templates/chimere/blocks/routing.html:14 +msgid "Search" +msgstr "Rechercher" + +#: templates/chimere/blocks/routing.html:20 msgid "Modify" msgstr "Modifier" -#: templates/chimere/blocks/routing.html:22 +#: templates/chimere/blocks/routing.html:23 msgid "New search" msgstr "Nouvelle recherche" -#: templates/chimere/blocks/routing.html:27 +#: templates/chimere/blocks/routing.html:31 msgid "Start:" msgstr "Départ :" -#: templates/chimere/blocks/routing.html:31 +#: templates/chimere/blocks/routing.html:35 msgid "Finish:" msgstr "Arrivée :" diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 640fc29..023c037 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -321,23 +321,23 @@ ul#action-2 { max-width:280px; } -ul#share{ +ul.share{ list-style-type:none; margin:0; padding:0; } -ul#share li{ +ul.share li{ display:inline; line-height:22px; vertical-align: bottom; } -#share a{ +.share a{ text-decoration:None; } -#share img{ +.share img{ border:None; width:22px; height:22px; diff --git a/chimere/static/chimere/img/feed.png b/chimere/static/chimere/img/feed.png new file mode 100644 index 0000000..19d2246 Binary files /dev/null and b/chimere/static/chimere/img/feed.png differ diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 4bc487e..ca664de 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -467,7 +467,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } /* show the popup */ if (settings.current_popup != null) { - settings.current_popup.hide(); + settings.current_popup.hide(); } if (feature.popup == null) { feature.popup = feature.createPopup(); @@ -484,6 +484,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } var markerClick = function (evt) { settings.current_feature = feature; + settings.current_position = feature.lonlat; if ( settings.on_marker_click ) { settings.on_marker_click(evt, mark, settings); } diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html index 95e6a70..2bd55aa 100644 --- a/chimere/templates/chimere/detail.html +++ b/chimere/templates/chimere/detail.html @@ -29,10 +29,11 @@ {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %} {{share_network.0}} {% endfor %}{%else%} -
{% endif%} diff --git a/chimere/urls.py b/chimere/urls.py index 81263a0..a23af1b 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -54,7 +54,7 @@ if settings.CHIMERE_FEEDS: if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^(?P[a-zA-Z0-9_-]*/)?route/'\ - r'(?P(%s))/' + r'(?P(%s))/((?P[0-9][0-9]*)/)?' r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)_'\ r'(?P([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ r'(?P[-]?[0-9]+[.]?[0-9]*)_(?P[-]?[0-9]+[.]?[0-9]*)$' % diff --git a/chimere/views.py b/chimere/views.py index adbcf7d..e8fb622 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -647,7 +647,7 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''): return HttpResponseRedirect(response_dct['extra_url'] + parameters) def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, - transport='foot'): + transport='foot', speed=''): ''' Get the JSON for a route ''' @@ -660,7 +660,7 @@ def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2, except ValueError: return HttpResponse('no results') jsons, desc, total = router.route(lon1, lat1, lon2, lat2, steps=steps, - transport=transport) + transport=transport, speed=speed) if not jsons: return HttpResponse('no results') jsonencoder = simplejson.JSONEncoder() -- cgit v1.2.3 From 741baf714a56ec15e38f42a5aef01868d3b80c6a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 31 Aug 2012 02:40:32 +0200 Subject: Routing: fix speed filter widget --- chimere/templates/chimere/blocks/routing.html | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html index 3c5e88e..40d2791 100644 --- a/chimere/templates/chimere/blocks/routing.html +++ b/chimere/templates/chimere/blocks/routing.html @@ -61,27 +61,28 @@ $(document).ready(function() { $('#main-map').chimere('route'); }); + var detached_speeds = Array(); function filter_speed(transport){ $("#id_speed_div").show(); + for (i=0;i {% endif%} -- cgit v1.2.3 From d1f5d131e6984d671670b8901e9449577fafae75 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 2 Sep 2012 19:59:06 +0200 Subject: Routing: finish work on add step - extract JS routing in a specific JS file --- chimere/static/chimere/js/jquery.chimere.js | 105 ++++++++++++++++----- chimere/static/chimere/js/nominatim-widget.js | 80 ++++++++-------- chimere/static/chimere/js/routing-widget.js | 47 +++++++++ chimere/templates/chimere/blocks/head_chimere.html | 1 + chimere/templates/chimere/blocks/routing.html | 49 +--------- chimere/templatetags/chimere_tags.py | 1 + 6 files changed, 177 insertions(+), 106 deletions(-) create mode 100644 chimere/static/chimere/js/routing-widget.js diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index a80a9ea..04beda5 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -95,6 +95,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { 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 @@ -322,6 +323,11 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.map.setCenter(settings.current_position); }, + // set current position + setCurrentPosition: function(lonlat){ + settings.current_position = lonlat; + }, + /* * Display menu on the map */ @@ -330,8 +336,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { if ($('#chimere_map_menu').is(":visible")){ $('#chimere_map_menu').hide(); } else{ - settings.current_position = - settings.map.getLonLatFromViewPortPx(e.xy); + methods.setCurrentPosition( + settings.map.getLonLatFromViewPortPx(e.xy)); var offsetX = e.pageX; var offsetY = e.pageY; $('#chimere_map_menu').show('fast'); @@ -521,7 +527,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { var markerClick = function (evt) { settings.current_feature = feature; - settings.current_position = feature.lonlat; + methods.setCurrentPosition(feature.lonlat); if ( settings.on_marker_click ) { settings.on_marker_click(evt, mark, settings); } @@ -595,25 +601,40 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.current_feature.geometry = linestring; settings.layerVectors.addFeatures([settings.current_feature]); }, - routingInputChange: function(){ + routingInputChange: function(nominatim_id){ $('#map_menu_clear').show(); - if ($('#nominatim_start_lon').val()){ - settings.routing_start = new OpenLayers.Marker( - new OpenLayers.LonLat($('#nominatim_start_lon').val(), - $('#nominatim_start_lat').val() - ).transform(EPSG_DISPLAY_PROJECTION, - settings.map.getProjectionObject()), - settings.icon_start); - settings.layerRouteMarker.addMarker(settings.routing_start); - } - if ($('#nominatim_end_lon').val()){ - settings.routing_end = new OpenLayers.Marker( - new OpenLayers.LonLat($('#nominatim_end_lon').val(), - $('#nominatim_end_lat').val() - ).transform(EPSG_DISPLAY_PROJECTION, - settings.map.getProjectionObject()), - settings.icon_end); - settings.layerRouteMarker.addMarker(settings.routing_end); + 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) { @@ -648,9 +669,48 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { 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("#nominatim_start_label").attr('id', c_id+'_label' + ).html(''); + cloned.children('label[for="id_start"]').html(step_label + ).attr('for', ""); + 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(); @@ -684,12 +744,14 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { $('#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; }, @@ -1134,6 +1196,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { }, success: function (data) { vals = $.parseJSON(data); + $('#'+response_id).html(vals.display_name); $('#nominatim_'+response_id).html(vals.display_name); $('#chimere_'+response_id).html(vals.display_name); } diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js index e925cf2..2ac9d1b 100644 --- a/chimere/static/chimere/js/nominatim-widget.js +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -1,42 +1,44 @@ var default_nominatim_lbl = ''; -$(function(){ - $(".nominatim-widget").autocomplete({ - source: function (request, response) { - $.ajax({ - url: nominatim_url, - data: { - format: "json", - q: request.term, - }, - success: function ( data ) { - response ( $.map( $.parseJSON(data), function( item ) { - return { - label: item.display_name, - value: item.display_name, - lat: item.lat, - lon: item.lon - } - })); +var nominatim_widget_options = { + source: function (request, response) { + $.ajax({ + url: nominatim_url, + data: { + format: "json", + q: request.term, + }, + success: function ( data ) { + response ( $.map( $.parseJSON(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" ); + } +} - } - }) - }, - 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"); - 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..043c957 --- /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{% endfor %} {% for js_url in OSM_JS_URLS %} {% endfor %} +{% if routing %}{% endif %} {% endif%} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 99ee0aa..11eed0d 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -108,6 +108,7 @@ 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 } return context_data -- cgit v1.2.3 From b6fe7084e905fbd29ea5de5e27ab7c6c29138fd6 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 3 Sep 2012 10:07:59 +0200 Subject: Enable translation of routing transport widget --- chimere/forms.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/chimere/forms.py b/chimere/forms.py index cb21f65..1eb5930 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -505,10 +505,13 @@ class AreaForm(AreaAdminForm): class Meta: model = Area +CHIMERE_ROUTING_TRANSPORT = [(idx, _(lbl)) + for idx, lbl in settings.CHIMERE_ROUTING_TRANSPORT] + class RoutingForm(forms.Form): transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, - choices=settings.CHIMERE_ROUTING_TRANSPORT, - initial=settings.CHIMERE_ROUTING_TRANSPORT[0][0]) + choices=CHIMERE_ROUTING_TRANSPORT, + initial=CHIMERE_ROUTING_TRANSPORT[0][0]) start = forms.CharField(label=_(u"Start"), widget=NominatimWidget) end = forms.CharField(label=_(u"Finish"), widget=NominatimWidget) speed = forms.ChoiceField(label=_(u"Speed"), choices=[], -- cgit v1.2.3 From 101310bc8e9f2731755b45241a74315e67061786 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 3 Sep 2012 10:18:10 +0200 Subject: Update of french translation --- chimere/forms.py | 2 +- chimere/locale/fr/LC_MESSAGES/django.po | 383 +++++++++++++++++++------------- 2 files changed, 234 insertions(+), 151 deletions(-) diff --git a/chimere/forms.py b/chimere/forms.py index 1eb5930..32f6d30 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -525,4 +525,4 @@ class RoutingForm(forms.Form): 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)) + ("%s_%d" % (transport, speed), _(lbl))) diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index e61f709..2f8cd3d 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,17 +7,17 @@ msgid "" msgstr "" "Project-Id-Version: 2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-26 17:07+0200\n" +"POT-Creation-Date: 2012-09-03 10:13+0200\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:8 models.py:526 +#: __init__.py:8 models.py:548 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: __init__.py:9 models.py:583 +#: __init__.py:9 models.py:605 msgid "Picture files" msgstr "Fichiers d'image" @@ -45,31 +45,31 @@ msgstr "Flux RSS" msgid "Contact us" msgstr "Nous contacter" -#: admin.py:62 templates/chimere/feeds/rss.html:69 +#: admin.py:63 templates/chimere/feeds/rss.html:69 msgid "Validate" msgstr "Valider" -#: admin.py:73 +#: admin.py:74 msgid "Export to KML" msgstr "Exporter en KML" -#: admin.py:87 +#: admin.py:88 msgid "Export to Shapefile" msgstr "Exporter en Shapefile" -#: admin.py:173 +#: admin.py:174 msgid "Import" msgstr "Import" -#: admin.py:179 +#: admin.py:180 msgid "Cancel import" msgstr "Annuler l'import" -#: admin.py:185 +#: admin.py:186 msgid "Cancel export" msgstr "Annuler l'export" -#: admin.py:193 +#: admin.py:194 msgid "Export to osm" msgstr "Exporter vers osm" @@ -106,51 +106,52 @@ msgstr "Courriel (optionnel) " msgid "Object" msgstr "Objet" -#: forms.py:163 +#: forms.py:164 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:174 +#: forms.py:175 msgid "This field is mandatory for the selected categories" msgstr "Ce champ est obligatoire pour les catégories sélectionnées" -#: forms.py:388 +#: forms.py:436 msgid "File" msgstr "Fichier" -#: forms.py:394 +#: forms.py:442 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:399 models.py:50 models.py:103 models.py:124 models.py:137 -#: models.py:151 models.py:234 models.py:473 models.py:516 models.py:560 -#: models.py:643 models.py:881 models.py:893 models.py:978 +#: forms.py:447 models.py:50 models.py:103 models.py:124 models.py:137 +#: models.py:151 models.py:243 models.py:482 models.py:538 models.py:582 +#: models.py:699 models.py:937 models.py:949 models.py:1034 #: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 +#: templates/chimere/blocks/alternate_multimedia.html:39 msgid "Name" msgstr "Nom" -#: forms.py:408 models.py:930 +#: forms.py:456 models.py:986 msgid "Area" msgstr "Zone" -#: forms.py:464 +#: forms.py:515 msgid "Start" msgstr "Départ" -#: forms.py:465 +#: forms.py:516 msgid "Finish" msgstr "Arrivée :" -#: forms.py:466 +#: forms.py:517 msgid "Speed" msgstr "Vitesse" -#: models.py:51 models.py:125 models.py:152 models.py:245 models.py:477 -#: models.py:899 models.py:980 +#: models.py:51 models.py:125 models.py:152 models.py:254 models.py:486 +#: models.py:955 models.py:1036 models.py:1072 msgid "Available" msgstr "Disponible" -#: models.py:52 models.py:989 +#: models.py:52 models.py:1045 msgid "Date" msgstr "Date" @@ -174,8 +175,8 @@ msgstr "Thème de couleur" msgid "Code" msgstr "Code" -#: models.py:113 models.py:126 models.py:156 models.py:518 models.py:575 -#: models.py:898 models.py:967 models.py:979 +#: models.py:113 models.py:126 models.py:156 models.py:540 models.py:597 +#: models.py:954 models.py:1023 models.py:1035 msgid "Order" msgstr "Ordre" @@ -187,15 +188,16 @@ msgstr "Couleur" msgid "Category" msgstr "Catégorie" -#: models.py:138 models.py:469 models.py:561 models.py:708 +#: models.py:138 models.py:478 models.py:583 models.py:764 +#: templates/chimere/blocks/alternate_multimedia.html:43 msgid "Image" msgstr "Image" -#: models.py:140 models.py:563 models.py:710 +#: models.py:140 models.py:585 models.py:766 msgid "Height" msgstr "Hauteur" -#: models.py:141 models.py:564 models.py:711 +#: models.py:141 models.py:586 models.py:767 msgid "Width" msgstr "Largeur" @@ -204,287 +206,307 @@ msgid "Icon" msgstr "Icône" #: models.py:157 +msgid "Is dated" +msgstr "Est daté" + +#: models.py:158 msgid "Marker" msgstr "Point d'intérêt" -#: models.py:158 models.py:704 models.py:719 +#: models.py:159 models.py:760 models.py:775 #: templates/chimere/edit_route.html:27 msgid "Route" msgstr "Trajet" -#: models.py:159 +#: models.py:160 msgid "Both" msgstr "Mixte" -#: models.py:160 +#: models.py:161 msgid "Item type" msgstr "Type d'élément" -#: models.py:165 +#: models.py:166 msgid "Sub-category" msgstr "Sous-catégorie" -#: models.py:166 +#: models.py:167 msgid "Sub-categories" msgstr "Sous-catégories" -#: models.py:212 +#: models.py:221 msgid "Importer type" msgstr "Type d'import" -#: models.py:215 models.py:256 +#: models.py:224 models.py:265 msgid "Source" msgstr "Source" -#: models.py:217 +#: models.py:226 msgid "Filter" msgstr "Filtre" -#: models.py:220 +#: models.py:229 msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:221 +#: models.py:230 msgid "State" msgstr "État" -#: models.py:223 +#: models.py:232 msgid "SRID" msgstr "SRID" -#: models.py:224 +#: models.py:233 msgid "Zipped file" msgstr "Fichier zippé" -#: models.py:227 +#: models.py:236 msgid "Importer" msgstr "Import" -#: models.py:236 +#: models.py:245 msgid "Submitter session key" msgstr "Clé de session du demandeur" -#: models.py:238 +#: models.py:247 msgid "Submitter name or nickname" msgstr "Nom ou pseudo du demandeur" -#: models.py:240 +#: models.py:249 msgid "Submitter email" msgstr "Courriel du demandeur" -#: models.py:242 +#: models.py:251 msgid "Submitter comment" msgstr "Commentaire du demandeur" -#: models.py:244 +#: models.py:253 msgid "Submited" msgstr "Soumis" -#: models.py:246 +#: models.py:255 msgid "Modified" msgstr "Modifié" -#: models.py:247 +#: models.py:256 msgid "Disabled" msgstr "Désactivé" -#: models.py:248 +#: models.py:257 msgid "Imported" msgstr "Importé" -#: models.py:249 +#: models.py:258 msgid "Excluded" msgstr "Exclu" -#: models.py:251 +#: models.py:260 msgid "Status" msgstr "État" -#: models.py:252 +#: models.py:261 msgid "Import key" msgstr "Clé d'import" -#: models.py:254 +#: models.py:263 msgid "Import version" msgstr "Version de l'import" -#: models.py:259 templates/chimere/edit.html:56 +#: models.py:268 templates/chimere/edit.html:56 #: templates/chimere/edit_route.html:52 msgid "Start date" msgstr "Date de début" -#: models.py:260 +#: models.py:269 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:262 templates/chimere/edit.html:62 +#: models.py:271 templates/chimere/edit.html:62 #: templates/chimere/edit_route.html:58 msgid "End date" msgstr "Date de fin" -#: models.py:263 +#: models.py:272 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:295 +#: models.py:304 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:296 +#: models.py:305 msgid "Localisation" msgstr "Localisation" -#: models.py:298 +#: models.py:307 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:302 templates/chimere/edit.html:49 +#: models.py:311 templates/chimere/edit.html:49 #: templates/chimere/edit_route.html:46 msgid "Description" msgstr "Description" -#: models.py:373 models.py:1009 +#: models.py:382 models.py:1082 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:467 +#: models.py:476 msgid "Audio" msgstr "Audio" -#: models.py:468 +#: models.py:477 msgid "Video" msgstr "Vidéo" -#: models.py:470 +#: models.py:479 msgid "Other" msgstr "Autre" -#: models.py:471 +#: models.py:480 msgid "Media type" msgstr "Type de media" -#: models.py:474 +#: models.py:483 msgid "Mime type" msgstr "Type mime" -#: models.py:476 +#: models.py:485 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:480 +#: models.py:489 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:481 +#: models.py:490 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:517 +#: models.py:525 +msgid "Extension name" +msgstr "" + +#: models.py:527 +msgid "Associated multimedia type" +msgstr "Type de multimedia associé" + +#: models.py:531 +msgid "Multimedia extension" +msgstr "Extension de fichier multimedia" + +#: models.py:532 +msgid "Multimedia extensions" +msgstr "Extensions de fichier multimedia" + +#: models.py:539 msgid "Url" msgstr "Url" -#: models.py:520 models.py:565 +#: models.py:542 models.py:587 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:525 +#: models.py:547 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:567 +#: models.py:589 msgid "Thumbnail" msgstr "Miniature" -#: models.py:571 +#: models.py:593 msgid "Thumbnail height" msgstr "Hauteur de la miniature" -#: models.py:573 +#: models.py:595 msgid "Thumbnail width" msgstr "Largeur de la miniature" -#: models.py:582 +#: models.py:604 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:644 +#: models.py:700 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:645 +#: models.py:701 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:647 +#: models.py:703 msgid "KML" msgstr "KML" -#: models.py:647 +#: models.py:703 msgid "GPX" msgstr "GPX" -#: models.py:652 +#: models.py:708 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:653 +#: models.py:709 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:703 +#: models.py:759 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:707 +#: models.py:763 msgid "Associated file" msgstr "Fichier associé" -#: models.py:882 +#: models.py:938 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:888 +#: models.py:944 msgid "Layer" msgstr "Couche" -#: models.py:894 +#: models.py:950 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:896 templates/chimere/blocks/welcome.html:3 +#: models.py:952 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:900 +#: models.py:956 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:902 +#: models.py:958 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:904 +#: models.py:960 msgid "Default area" msgstr "Zone par défaut" -#: models.py:905 +#: models.py:961 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:909 +#: models.py:965 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:911 +#: models.py:967 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:912 +#: models.py:968 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -492,68 +514,76 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:916 models.py:983 +#: models.py:972 models.py:1039 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:917 +#: models.py:973 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:919 +#: models.py:975 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:921 +#: models.py:977 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:968 +#: models.py:1024 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:972 models.py:973 +#: models.py:1028 models.py:1029 msgid "Layers" msgstr "Couches" -#: models.py:981 +#: models.py:1037 msgid "Mandatory" msgstr "Obligatoire" -#: models.py:984 +#: models.py:1040 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:986 +#: models.py:1042 msgid "Text" msgstr "Texte" -#: models.py:987 +#: models.py:1043 msgid "Long text" msgstr "Texte long" -#: models.py:988 +#: models.py:1044 msgid "Password" msgstr "Mot de passe" -#: models.py:994 +#: models.py:1046 +msgid "Choices" +msgstr "Choix" + +#: models.py:1054 msgid "Type" msgstr "Type" -#: models.py:999 models.py:1011 +#: models.py:1059 models.py:1070 models.py:1084 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:1012 +#: models.py:1071 models.py:1085 msgid "Value" msgstr "Valeur" -#: models.py:1016 +#: models.py:1077 +msgid "Model property choice" +msgstr "Choix pour les modèles de propriété" + +#: models.py:1096 msgid "Property" msgstr "Propriété" @@ -653,19 +683,19 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:237 +#: views.py:238 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:319 +#: views.py:320 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:441 +#: views.py:442 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:444 +#: views.py:445 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." @@ -674,52 +704,52 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:448 +#: views.py:449 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:584 +#: views.py:586 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:716 +#: views.py:718 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:180 +#: widgets.py:204 msgid "Street, City, Country" msgstr "Rue, Commune, Pays" -#: widgets.py:246 +#: widgets.py:270 msgid "Latitude" msgstr "Latitude" -#: widgets.py:246 +#: widgets.py:270 msgid "Longitude" msgstr "Longitude" -#: widgets.py:271 +#: widgets.py:295 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:321 +#: widgets.py:345 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:322 +#: widgets.py:346 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:324 +#: widgets.py:348 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:325 +#: widgets.py:349 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:326 +#: widgets.py:350 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -727,7 +757,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:328 +#: widgets.py:352 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -735,17 +765,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:333 +#: widgets.py:357 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:334 +#: widgets.py:358 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:335 +#: widgets.py:359 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -753,7 +783,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:337 +#: widgets.py:361 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -762,33 +792,33 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:344 +#: widgets.py:368 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:347 +#: widgets.py:371 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:348 +#: widgets.py:372 msgid "or" msgstr "ou" -#: widgets.py:353 +#: widgets.py:377 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:376 +#: widgets.py:400 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:376 +#: widgets.py:400 msgid "Draw" msgstr "Tracer" -#: widgets.py:501 +#: widgets.py:525 msgid "Select..." msgstr "Sélectionner..." @@ -893,7 +923,7 @@ msgstr "Commentaires au sujet de votre proposition" msgid "Upload in progress. Please wait..." msgstr "Traitement en cours. Veuillez patienter..." -#: templates/chimere/edit.html:151 templates/chimere/edit_route.html:77 +#: templates/chimere/edit.html:152 templates/chimere/edit_route.html:77 msgid "Propose" msgstr "Proposez" @@ -917,6 +947,54 @@ msgstr "Déposer un fichier" msgid "Upload" msgstr "Déposer" +#: templates/chimere/blocks/alternate_multimedia.html:33 +#: templates/chimere/blocks/alternate_multimedia.html:51 +msgid "Add" +msgstr "Ajouter" + +#: templates/chimere/blocks/alternate_multimedia.html:35 +msgid "Add multimedia from your computer or a website" +msgstr "Ajouter du multimedia depuis votre ordinateur ou un site web" + +#: 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 " +"vel odio porta vulputate." +msgstr "" + +#: templates/chimere/blocks/alternate_multimedia.html:44 +msgid "Audio, video, other..." +msgstr "Audio, vidéo, autre..." + +#: templates/chimere/blocks/alternate_multimedia.html:47 +msgid "Download" +msgstr "Téléchargement" + +#: templates/chimere/blocks/alternate_multimedia.html:48 +msgid "Or" +msgstr "Ou" + +#: templates/chimere/blocks/alternate_multimedia.html:49 +msgid "Web address" +msgstr "Adresse web" + +#: templates/chimere/blocks/alternate_multimedia.html:80 +msgid "You must provide a name." +msgstr "Vous devez donner un nom." + +#: templates/chimere/blocks/alternate_multimedia.html:85 +msgid "You must choose a media type." +msgstr "Voux devez choisir un type de média." + +#: templates/chimere/blocks/alternate_multimedia.html:91 +msgid "You must provide a file or a web address." +msgstr "Vous devez fournir un fichier ou une adresse web." + +#: templates/chimere/blocks/alternate_multimedia.html:96 +msgid "You must provide a web address." +msgstr "Voux devez donner une adresse web." + #: templates/chimere/blocks/areas.html:4 msgid "Areas:" msgstr "Zones :" @@ -990,31 +1068,38 @@ msgstr "" "Utilisez un navigateur internet plus récent ou installez le greffon non " "libre Flash." -#: templates/chimere/blocks/routing.html:4 -#: templates/chimere/blocks/routing.html:44 +#: templates/chimere/blocks/routing.html:5 msgid "Itinerary" msgstr "Itinéraire" -#: templates/chimere/blocks/routing.html:14 +#: 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:20 +#: templates/chimere/blocks/routing.html:23 msgid "Modify" msgstr "Modifier" -#: templates/chimere/blocks/routing.html:23 +#: templates/chimere/blocks/routing.html:26 msgid "New search" msgstr "Nouvelle recherche" -#: templates/chimere/blocks/routing.html:31 +#: templates/chimere/blocks/routing.html:34 msgid "Start:" msgstr "Départ :" -#: templates/chimere/blocks/routing.html:35 +#: templates/chimere/blocks/routing.html:38 msgid "Finish:" msgstr "Arrivée :" +#: templates/chimere/blocks/routing.html:43 +msgid "Step" +msgstr "Étape" + #: templates/chimere/blocks/submited.html:3 msgid "" "Your new proposition/modification has been submited. A moderator will treat " @@ -1079,5 +1164,3 @@ msgstr "Choisir une zone pré-définie" msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" -#~ msgid "End" -#~ msgstr "Fin" -- cgit v1.2.3 From 4b1c3fa5d3a47b5388fb88e4adf5e78388535e69 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 3 Sep 2012 12:45:23 +0200 Subject: JS: fix ajax call to force JSON response --- chimere/static/chimere/js/jquery.chimere.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 04beda5..6a8dbed 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -1194,8 +1194,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { lat:lonlat.lat, lon:lonlat.lon }, - success: function (data) { - vals = $.parseJSON(data); + 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); -- cgit v1.2.3 From c89ba34380c86f8853a5e6af6cee345002ca381b Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 3 Sep 2012 12:54:06 +0200 Subject: JS: fix ajax call to force JSON response (bis) --- chimere/static/chimere/js/nominatim-widget.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js index 2ac9d1b..80aa03a 100644 --- a/chimere/static/chimere/js/nominatim-widget.js +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -7,8 +7,9 @@ var nominatim_widget_options = { format: "json", q: request.term, }, + dataType:'json', success: function ( data ) { - response ( $.map( $.parseJSON(data), function( item ) { + response ( $.map(data, function(item) { return { label: item.display_name, value: item.display_name, -- cgit v1.2.3 From e0f0fa81482618d160b665431ce7273ceb2165b0 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 4 Sep 2012 00:13:01 +0200 Subject: Add a new Page model to add simple pages as "actions"- Improve actions management --- chimere/actions.py | 39 +++- chimere/admin.py | 11 +- chimere/forms.py | 11 +- chimere/migrations/0032_auto__add_page.py | 252 ++++++++++++++++++++++ chimere/models.py | 27 +++ chimere/templates/chimere/blocks/actions.html | 4 +- chimere/templates/chimere/default_extra_page.html | 14 ++ chimere/urls.py | 5 +- chimere/views.py | 40 +++- 9 files changed, 380 insertions(+), 23 deletions(-) create mode 100644 chimere/migrations/0032_auto__add_page.py create mode 100644 chimere/templates/chimere/default_extra_page.html diff --git a/chimere/actions.py b/chimere/actions.py index 0363d54..a434279 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+'/'] + 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 92e971d..2125bef 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -35,13 +35,12 @@ except ImportError: pass from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ - NewsAdminForm, CategoryAdminForm, ImporterAdminForm + NewsAdminForm, CategoryAdminForm, ImporterAdminForm, PageAdminForm from chimere.models import Category, Icon, SubCategory, Marker, \ PropertyModel, News, Route, Area, ColorTheme, Color, RouteFile,\ MultimediaType, MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ - PropertyModelChoice, MultimediaExtension + PropertyModelChoice, MultimediaExtension, Page from chimere.utils import unicode_normalize, ShapefileManager, KMLManager -from chimere.widgets import TextareaWidget def get_areas_for_user(user): """ @@ -201,6 +200,11 @@ class ImporterAdmin(admin.ModelAdmin): actions = [importing, cancel_import, cancel_export] admin.site.register(Importer, ImporterAdmin) +class PageAdmin(admin.ModelAdmin): + """ + Use the TinyMCE widget for the page content + """ + form = PageAdminForm class NewsAdmin(admin.ModelAdmin): """ @@ -252,6 +256,7 @@ 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 32f6d30..b8bd7b1 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -33,7 +33,8 @@ from django.core.mail import EmailMessage, BadHeaderError from chimere.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ - PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, MultimediaExtension + PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, \ + MultimediaExtension, Page from chimere.widgets import AreaField, PointField, TextareaWidget, \ DatePickerWidget, ButtonSelectWidget, NominatimWidget @@ -94,6 +95,14 @@ class ContactForm(forms.Form): email = forms.EmailField(label=_("Email (optional)"), required=False) content = forms.CharField(label=_("Object"), widget=forms.Textarea) +class PageAdminForm(forms.ModelForm): + """ + Main form for extra pages + """ + content = forms.CharField(widget=TextareaWidget) + class Meta: + model = Page + class NewsAdminForm(forms.ModelForm): """ Main form for news diff --git a/chimere/migrations/0032_auto__add_page.py b/chimere/migrations/0032_auto__add_page.py new file mode 100644 index 0000000..e39c4a8 --- /dev/null +++ b/chimere/migrations/0032_auto__add_page.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model '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']) + + + def backwards(self, orm): + # Deleting model 'Page' + db.delete_table('chimere_page') + + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}), + 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'restrict_to_extent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'db_table': "'chimere_subcategory_areas'", 'to': "orm['chimere.SubCategory']"}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'blank': 'True'}), + 'welcome_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.arealayers': { + 'Meta': {'ordering': "('order',)", 'object_name': 'AreaLayers'}, + 'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Area']"}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Layer']"}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.color': { + 'Meta': {'ordering': "['order']", 'object_name': 'Color'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.colortheme': { + 'Meta': {'object_name': 'ColorTheme'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.icon': { + 'Meta': {'object_name': 'Icon'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.importer': { + 'Meta': {'object_name': 'Importer'}, + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'chimere.layer': { + 'Meta': {'object_name': 'Layer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'point': ('chimere.widgets.PointField', [], {}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.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']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'chimere.multimediatype': { + 'Meta': {'object_name': 'MultimediaType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'content': ('django.db.models.fields.TextField', [], {}), + 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.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', [], {}), + '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', [], {}) + }, + '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'}), + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'}, + 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.subcategory': { + 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] \ No newline at end of file diff --git a/chimere/models.py b/chimere/models.py index 5c98de7..9ff442b 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -44,6 +44,33 @@ from chimere.widgets import PointField, RouteField, SelectMultipleField, \ from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager +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) + class News(models.Model): """News of the site """ 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 @@ @@ -11,7 +11,7 @@ {% ifequal action.id action_selected.0 %}{% if subactions %} {% for subaction in subactions %}
  • - {{ subaction.label }} + {{ subaction.label }}
  • {% endfor %} {% endif %}{% endifequal %} diff --git a/chimere/templates/chimere/default_extra_page.html b/chimere/templates/chimere/default_extra_page.html new file mode 100644 index 0000000..337a991 --- /dev/null +++ b/chimere/templates/chimere/default_extra_page.html @@ -0,0 +1,14 @@ +{% 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 }} + {{content|safe}} +{% endblock %} + diff --git a/chimere/urls.py b/chimere/urls.py index a23af1b..086be3f 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -64,7 +64,8 @@ if settings.CHIMERE_ENABLE_ROUTING: urlpatterns += patterns('chimere.views', url(r'^charte/?$', 'charte', name="charte"), - url(r'^(?P[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', name="contact"), + url(r'^(?P[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', + name="contact"), url(r'^(?P[a-zA-Z0-9_-]+/)?edit/$', 'edit', name="edit"), url(r'^(?P[a-zA-Z0-9_-]+/)?edit/(?P\w+)/(?P\w+)?$', @@ -88,6 +89,8 @@ urlpatterns += patterns('chimere.views', 'uploadFile', name='upload_file'), url(r'^(?P[a-zA-Z0-9_-]+/)?process_route_file/(?P\d+)/$', 'processRouteFile', name='process_route_file'), + url(r'^(?P[a-zA-Z0-9_-]+/)?dyn/(?P\w+)/$', + 'extraPage', name='extra_page'), # At the end, because it catches large url(r'^(?P[a-zA-Z0-9_-]+)?', 'index', name="index"), ) diff --git a/chimere/views.py b/chimere/views.py index 4a97a62..366ac1a 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -41,7 +41,7 @@ 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, \ +from chimere.models import Category, SubCategory, PropertyModel, Page,\ Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile from chimere.widgets import getMapJS, PointChooserWidget, \ @@ -127,7 +127,8 @@ def index(request, area_name=None, default_area=None, simple=False): if settings.CHIMERE_ENABLE_ROUTING: response_dct['itinerary_form'] = RoutingForm() 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, @@ -265,7 +266,7 @@ def edit(request, area_name="", item_id=None, submited=False): filtered_properties = PropertyModel.objects.filter(available=True, subcategories__id__isnull=False).all() response_dct.update({ - 'actions':actions, + 'actions':actions(response_dct['area_name']), 'action_selected':('contribute', 'edit'), 'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER, 'form':form, @@ -370,7 +371,7 @@ def editRoute(request, area_name="", item_id=None, submited=False): if 'description' in declared_fields: declared_fields.pop(declared_fields.index('description')) 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, @@ -413,7 +414,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)) @@ -424,7 +426,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)) @@ -452,11 +455,31 @@ 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}) + 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 @@ -679,7 +702,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": -- cgit v1.2.3 From 736fbe38b7ba73b6c05bcf2a6d2216a5aee0ffa0 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 4 Sep 2012 00:47:10 +0200 Subject: Add title to extra pages --- chimere/templates/chimere/default_extra_page.html | 1 + chimere/views.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/chimere/templates/chimere/default_extra_page.html b/chimere/templates/chimere/default_extra_page.html index 337a991..884d4cc 100644 --- a/chimere/templates/chimere/default_extra_page.html +++ b/chimere/templates/chimere/default_extra_page.html @@ -9,6 +9,7 @@ {% block message_edit%}{% endblock %} {% block content %} {{ block.super }} +

    {{title}}

    {{content|safe}} {% endblock %} diff --git a/chimere/views.py b/chimere/views.py index 366ac1a..1a6078f 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -474,7 +474,8 @@ def extraPage(request, area_name="", page_id=""): return redir response_dct.update({'actions':actions(response_dct['area_name']), 'action_selected':(page_id,), - 'content':page.content}) + '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, -- cgit v1.2.3 From 6275deca8d254139c1395197125b660d102339ed Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 4 Sep 2012 13:08:21 +0200 Subject: Improve tinyMCE edition for extra pages --- chimere/forms.py | 6 +++--- chimere/widgets.py | 33 +++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/chimere/forms.py b/chimere/forms.py index b8bd7b1..a5ad894 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -36,7 +36,7 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\ PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, \ MultimediaExtension, Page from chimere.widgets import AreaField, PointField, TextareaWidget, \ - DatePickerWidget, ButtonSelectWidget, NominatimWidget + FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget from datetime import timedelta, datetime, tzinfo @@ -99,7 +99,7 @@ class PageAdminForm(forms.ModelForm): """ Main form for extra pages """ - content = forms.CharField(widget=TextareaWidget) + content = forms.CharField(widget=FullTextareaWidget) class Meta: model = Page @@ -107,7 +107,7 @@ class NewsAdminForm(forms.ModelForm): """ Main form for news """ - content = forms.CharField(widget=TextareaWidget) + content = forms.CharField(widget=FullTextareaWidget) class Meta: model = News diff --git a/chimere/widgets.py b/chimere/widgets.py index a30b596..efc7aae 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -145,6 +145,7 @@ class TextareaWidget(forms.Textarea): class Media: js = ["%stiny_mce.js" % settings.TINYMCE_URL, "%schimere/js/textareas.js" % settings.STATIC_URL,] + def render(self, *args, **kwargs): if 'attrs' not in kwargs: kwargs['attrs'] = {} @@ -153,16 +154,13 @@ class TextareaWidget(forms.Textarea): else: kwargs['attrs']['class'] += ' ' kwargs['attrs']['class'] += 'mceEditor' - rendered = super(TextareaWidget, self).render(*args, **kwargs) - return mark_safe(rendered) - - def render(self, *args, **kwargs): rendered = super(TextareaWidget, self).render(*args, **kwargs) rendered += u""" +""" + return mark_safe(rendered) + class DatePickerWidget(forms.TextInput): """ Manage the edition of dates. -- cgit v1.2.3 From 827c69abb1c7908e871dde184020ebbb8b9f0b8d Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 5 Sep 2012 14:08:47 +0200 Subject: Add a text full MCE widget (for admin) --- chimere/static/chimere/js/textareas-full.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 chimere/static/chimere/js/textareas-full.js diff --git a/chimere/static/chimere/js/textareas-full.js b/chimere/static/chimere/js/textareas-full.js new file mode 100644 index 0000000..1200474 --- /dev/null +++ b/chimere/static/chimere/js/textareas-full.js @@ -0,0 +1,24 @@ +/* Copyright (C) 2012 Étienne Loks + +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 . + +See the file COPYING for details. +*/ + +tinyMCE.init({ + mode : "textareas", + theme : "advanced", + editor_selector : "mceEditor", + relative_urls : false +}); -- cgit v1.2.3 From 9122d84a69678a961eac5396956a9c6d8de99a90 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 5 Sep 2012 14:11:37 +0200 Subject: News and welcome message improvment (choose the news available on welcome and add a specific page for news) --- ...front_page__add_field_news_is_front_page__ad.py | 264 +++++++++++++++++++++ chimere/models.py | 53 +++-- chimere/templates/chimere/blocks/news.html | 53 +++++ chimere/templates/chimere/main_map.html | 1 + chimere/templatetags/chimere_tags.py | 38 ++- chimere/views.py | 15 +- 6 files changed, 390 insertions(+), 34 deletions(-) create mode 100644 chimere/migrations/0033_auto__add_field_marker_is_front_page__add_field_news_is_front_page__ad.py create mode 100644 chimere/templates/chimere/blocks/news.html diff --git a/chimere/migrations/0033_auto__add_field_marker_is_front_page__add_field_news_is_front_page__ad.py b/chimere/migrations/0033_auto__add_field_marker_is_front_page__add_field_news_is_front_page__ad.py new file mode 100644 index 0000000..9f37064 --- /dev/null +++ b/chimere/migrations/0033_auto__add_field_marker_is_front_page__add_field_news_is_front_page__ad.py @@ -0,0 +1,264 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Marker.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) + + # 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) + + + def backwards(self, orm): + # Deleting field 'Marker.is_front_page' + db.delete_column('chimere_marker', 'is_front_page') + + # Deleting field 'News.is_front_page' + db.delete_column('chimere_news', 'is_front_page') + + # Deleting field 'News.url' + db.delete_column('chimere_news', 'url') + + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}), + 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'restrict_to_extent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'db_table': "'chimere_subcategory_areas'", 'to': "orm['chimere.SubCategory']"}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'blank': 'True'}), + 'welcome_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.arealayers': { + 'Meta': {'ordering': "('order',)", 'object_name': 'AreaLayers'}, + 'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Area']"}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Layer']"}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.color': { + 'Meta': {'ordering': "['order']", 'object_name': 'Color'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.colortheme': { + 'Meta': {'object_name': 'ColorTheme'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.icon': { + 'Meta': {'object_name': 'Icon'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.importer': { + 'Meta': {'object_name': 'Importer'}, + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'chimere.layer': { + 'Meta': {'object_name': 'Layer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'point': ('chimere.widgets.PointField', [], {}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.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']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'chimere.multimediatype': { + 'Meta': {'object_name': 'MultimediaType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'content': ('django.db.models.fields.TextField', [], {}), + 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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', [], {}), + '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', [], {}) + }, + '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'}), + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'}, + 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.subcategory': { + 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] \ No newline at end of file diff --git a/chimere/models.py b/chimere/models.py index 9ff442b..dabe9fd 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -71,13 +71,37 @@ def page_post_save(sender, **kwargs): 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) def __unicode__(self): ordering = ["-date"] return self.title @@ -85,6 +109,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 """ @@ -336,6 +364,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): @@ -382,27 +412,8 @@ class Marker(GeographicItem): return self.start_date @property - def description_short(self): - if not self.description: - return '' - if len(self.description) <= settings.CHIMERE_SHORT_DESC_LENGTH: - return self.description - desc = self.description[: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 - short_desc += "..." - return BeautifulSoup(short_desc).prettify() + def short_desc(self): + return shortify(self.description) class Meta: ordering = ('status', 'name') 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 %} +{% trans "News"%} + + +{% endif %} + diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index 4a53b3f..9f220b5 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -23,6 +23,7 @@ {% display_areas %} {% endif %} {% routing %} + {% display_welcome %} {% display_news news_visible %}
    diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 11eed0d..2e5e1fe 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -9,6 +9,8 @@ from django import template from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse +from django.db.models import Q +from django.utils.translation import ugettext as _ from chimere.models import Marker, Area, News, SubCategory, MultimediaType from chimere.widgets import get_map_layers @@ -37,22 +39,29 @@ 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. - """ - context_data = {'display':display} +def get_news(): # Retrieve news - news = list(News.objects.filter(available=True)) + news = list(News.objects.filter(available=True, is_front_page=True)) if settings.CHIMERE_DAYS_BEFORE_EVENT: # Retrieve active markers today = date.today() after = today + timedelta(settings.CHIMERE_DAYS_BEFORE_EVENT) - news += list(Marker.objects.filter(status='A', end_date__gte=today, - start_date__lte=after)) + q = Q(end_date__gte=today) | Q(end_date__isnull=True) + news += list(Marker.objects.filter(status='A', + start_date__lte=after, is_front_page=True).filter(q)) news.sort(key=lambda x:x.date, reverse=True) - context_data['news_lst'] = news + 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} + context_data['news_lst'] = get_news()[:3] + context_data['STATIC_URL'] = settings.STATIC_URL + context_data['title'] = title if title \ + else _(u"Welcome to the %s") % settings.PROJECT_NAME if "area_name" in context: try: area = Area.objects.get(urn=context["area_name"]) @@ -62,6 +71,15 @@ def display_news(context, display=False): pass return context_data +@register.inclusion_tag('chimere/blocks/news.html', takes_context=True) +def display_news(context, title=''): + """ + All news. + """ + context_data = {'news_lst': get_news(), + 'STATIC_URL':settings.STATIC_URL} + return context_data + @register.inclusion_tag('chimere/blocks/head_jquery.html', takes_context=True) def head_jquery(context): """ diff --git a/chimere/views.py b/chimere/views.py index 1a6078f..a9b75a2 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -116,6 +116,7 @@ def index(request, area_name=None, default_area=None, simple=False): request.session['last_visit'] != today: request.session['last_visit'] = today news_visible = True + news_visible = True response_dct, redir = get_base_response(area_name) if redir: return redir @@ -398,12 +399,20 @@ def welcome(request, display=None): Welcome string """ response_dct = {'display':display} - news = list(News.objects.filter(available=True).all()) + news = list(News.objects.filter(available=True, is_front_page=True).all()) if settings.CHIMERE_DAYS_BEFORE_EVENT: - q = checkDate(Q(status='A', start_date__isnull=False)) + q = checkDate(Q(status='A', start_date__isnull=False, + is_front_page=True)) news += list(Marker.objects.filter(q).all()) - news.sort(key=lambda x:x.date, reverse=True) + news.sort(key=lambda x:x.date, reverse=True)[:3] response_dct['news_lst'] = news + 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 return loader.render_to_string('chimere/blocks/welcome.html', response_dct, context_instance=RequestContext(request)) -- cgit v1.2.3 From 6fcbad5390a8a7871744b8dff13ba9a5a96bf30b Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 5 Sep 2012 14:46:42 +0200 Subject: Fix tinyMCE widget --- chimere/widgets.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/chimere/widgets.py b/chimere/widgets.py index efc7aae..c0f08c7 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -143,8 +143,7 @@ class TextareaWidget(forms.Textarea): Manage the edition of a text using TinyMCE """ class Media: - js = ["%stiny_mce.js" % settings.TINYMCE_URL, - "%schimere/js/textareas.js" % settings.STATIC_URL,] + js = ["%stiny_mce.js" % settings.TINYMCE_URL] def render(self, *args, **kwargs): if 'attrs' not in kwargs: @@ -164,7 +163,8 @@ tinyMCE.init({ theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,hr,separator,link", theme_advanced_buttons2 : "", theme_advanced_buttons3 : "" -}); +}); + """ return mark_safe(rendered) @@ -173,8 +173,7 @@ class FullTextareaWidget(forms.Textarea): Manage the edition of a text using TinyMCE """ class Media: - js = ["%stiny_mce.js" % settings.TINYMCE_URL, - "%schimere/js/textareas-full.js" % settings.STATIC_URL,] + js = ["%stiny_mce.js" % settings.TINYMCE_URL] def render(self, *args, **kwargs): if 'attrs' not in kwargs: @@ -191,7 +190,8 @@ tinyMCE.init({ theme : "advanced", relative_urls : false, editor_selector : "mceEditor" -}); +}); + """ return mark_safe(rendered) -- cgit v1.2.3 From aaad3ceb8a0bbcd54288d5ccbb58ef25d72af4b6 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 5 Sep 2012 19:13:58 +0200 Subject: Update french translation --- chimere/locale/fr/LC_MESSAGES/django.po | 377 +++++++++++++++------------- chimere/static/chimere/js/textareas-full.js | 24 -- 2 files changed, 199 insertions(+), 202 deletions(-) delete mode 100644 chimere/static/chimere/js/textareas-full.js diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index 2f8cd3d..9a3c975 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,69 +7,69 @@ msgid "" msgstr "" "Project-Id-Version: 2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-03 10:13+0200\n" +"POT-Creation-Date: 2012-09-05 19:08+0200\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:8 models.py:548 +#: __init__.py:8 models.py:586 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: __init__.py:9 models.py:605 +#: __init__.py:9 models.py:643 msgid "Picture files" msgstr "Fichiers d'image" -#: 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" -#: admin.py:63 templates/chimere/feeds/rss.html:69 +#: admin.py:62 templates/chimere/feeds/rss.html:69 msgid "Validate" msgstr "Valider" -#: admin.py:74 +#: admin.py:73 msgid "Export to KML" msgstr "Exporter en KML" -#: admin.py:88 +#: admin.py:87 msgid "Export to Shapefile" msgstr "Exporter en Shapefile" -#: admin.py:174 +#: admin.py:173 msgid "Import" msgstr "Import" -#: admin.py:180 +#: admin.py:179 msgid "Cancel import" msgstr "Annuler l'import" -#: admin.py:186 +#: admin.py:185 msgid "Cancel export" msgstr "Annuler l'export" -#: admin.py:194 +#: admin.py:193 msgid "Export to osm" msgstr "Exporter vers osm" @@ -85,428 +85,445 @@ 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:81 +#: forms.py:82 msgid "New submission for" msgstr "Nouvelle proposition pour" -#: forms.py:82 +#: forms.py:83 #, 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:84 +#: forms.py:85 msgid "To valid, precise or unvalid this item: " msgstr "Pour valider, préciser ou rejeter cet élément : " -#: forms.py:94 +#: forms.py:95 msgid "Email (optional)" msgstr "Courriel (optionnel) " -#: forms.py:95 +#: forms.py:96 msgid "Object" msgstr "Objet" -#: forms.py:164 +#: forms.py:173 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:175 +#: forms.py:184 msgid "This field is mandatory for the selected categories" msgstr "Ce champ est obligatoire pour les catégories sélectionnées" -#: forms.py:436 +#: forms.py:445 msgid "File" msgstr "Fichier" -#: forms.py:442 +#: forms.py:451 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:447 models.py:50 models.py:103 models.py:124 models.py:137 -#: models.py:151 models.py:243 models.py:482 models.py:538 models.py:582 -#: models.py:699 models.py:937 models.py:949 models.py:1034 +#: forms.py:456 models.py:50 models.py:98 models.py:158 models.py:179 +#: models.py:192 models.py:206 models.py:298 models.py:520 models.py:576 +#: models.py:620 models.py:737 models.py:975 models.py:987 models.py:1072 #: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 #: templates/chimere/blocks/alternate_multimedia.html:39 msgid "Name" msgstr "Nom" -#: forms.py:456 models.py:986 +#: forms.py:465 models.py:1024 msgid "Area" msgstr "Zone" -#: forms.py:515 +#: forms.py:524 msgid "Start" msgstr "Départ" -#: forms.py:516 +#: forms.py:525 msgid "Finish" msgstr "Arrivée :" -#: forms.py:517 +#: forms.py:526 msgid "Speed" msgstr "Vitesse" -#: models.py:51 models.py:125 models.py:152 models.py:254 models.py:486 -#: models.py:955 models.py:1036 models.py:1072 +#: models.py:51 +msgid "Mnemonic" +msgstr "Mnémonique" + +#: models.py:53 models.py:99 models.py:180 models.py:207 models.py:309 +#: models.py:524 models.py:993 models.py:1074 models.py:1110 msgid "Available" msgstr "Disponible" -#: models.py:52 models.py:1045 +#: models.py:54 models.py:168 models.py:181 models.py:211 models.py:578 +#: models.py:635 models.py:992 models.py:1061 models.py:1073 +msgid "Order" +msgstr "Ordre" + +#: models.py:55 +msgid "Template path" +msgstr "Chemin du patron" + +#: models.py:62 models.py:63 +msgid "Page" +msgstr "Page" + +#: models.py:100 models.py:367 +msgid "Is front page" +msgstr "Est en page principale" + +#: models.py:102 models.py:1083 msgid "Date" msgstr "Date" -#: models.py:58 models.py:59 +#: models.py:104 models.py:577 +msgid "Url" +msgstr "Url" + +#: models.py:109 models.py:110 templates/chimere/blocks/news.html:3 +#: templates/chimere/blocks/news.html:5 msgid "News" msgstr "Nouvelle" -#: models.py:64 +#: models.py:119 msgid "Parameters" msgstr "Paramètres" -#: models.py:68 +#: models.py:123 msgid "TinyUrl" msgstr "Mini-url" -#: models.py:107 models.py:114 models.py:154 +#: models.py:162 models.py:169 models.py:209 msgid "Color theme" msgstr "Thème de couleur" -#: models.py:112 +#: models.py:167 msgid "Code" msgstr "Code" -#: models.py:113 models.py:126 models.py:156 models.py:540 models.py:597 -#: models.py:954 models.py:1023 models.py:1035 -msgid "Order" -msgstr "Ordre" - -#: models.py:119 +#: models.py:174 msgid "Color" msgstr "Couleur" -#: models.py:132 models.py:150 templates/chimere/main_map.html:13 +#: models.py:187 models.py:205 templates/chimere/main_map.html:13 msgid "Category" msgstr "Catégorie" -#: models.py:138 models.py:478 models.py:583 models.py:764 +#: models.py:193 models.py:516 models.py:621 models.py:802 #: templates/chimere/blocks/alternate_multimedia.html:43 msgid "Image" msgstr "Image" -#: models.py:140 models.py:585 models.py:766 +#: models.py:195 models.py:623 models.py:804 msgid "Height" msgstr "Hauteur" -#: models.py:141 models.py:586 models.py:767 +#: models.py:196 models.py:624 models.py:805 msgid "Width" msgstr "Largeur" -#: models.py:145 models.py:153 +#: models.py:200 models.py:208 msgid "Icon" msgstr "Icône" -#: models.py:157 +#: models.py:212 msgid "Is dated" msgstr "Est daté" -#: models.py:158 +#: models.py:213 msgid "Marker" msgstr "Point d'intérêt" -#: models.py:159 models.py:760 models.py:775 +#: models.py:214 models.py:798 models.py:813 #: templates/chimere/edit_route.html:27 msgid "Route" msgstr "Trajet" -#: models.py:160 +#: models.py:215 msgid "Both" msgstr "Mixte" -#: models.py:161 +#: models.py:216 msgid "Item type" msgstr "Type d'élément" -#: models.py:166 +#: models.py:221 msgid "Sub-category" msgstr "Sous-catégorie" -#: models.py:167 +#: models.py:222 msgid "Sub-categories" msgstr "Sous-catégories" -#: models.py:221 +#: models.py:276 msgid "Importer type" msgstr "Type d'import" -#: models.py:224 models.py:265 +#: models.py:279 models.py:320 msgid "Source" msgstr "Source" -#: models.py:226 +#: models.py:281 msgid "Filter" msgstr "Filtre" -#: models.py:229 +#: models.py:284 msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:230 +#: models.py:285 msgid "State" msgstr "État" -#: models.py:232 +#: models.py:287 msgid "SRID" msgstr "SRID" -#: models.py:233 +#: models.py:288 msgid "Zipped file" msgstr "Fichier zippé" -#: models.py:236 +#: models.py:291 msgid "Importer" msgstr "Import" -#: models.py:245 +#: models.py:300 msgid "Submitter session key" msgstr "Clé de session du demandeur" -#: models.py:247 +#: models.py:302 msgid "Submitter name or nickname" msgstr "Nom ou pseudo du demandeur" -#: models.py:249 +#: models.py:304 msgid "Submitter email" msgstr "Courriel du demandeur" -#: models.py:251 +#: models.py:306 msgid "Submitter comment" msgstr "Commentaire du demandeur" -#: models.py:253 +#: models.py:308 msgid "Submited" msgstr "Soumis" -#: models.py:255 +#: models.py:310 msgid "Modified" msgstr "Modifié" -#: models.py:256 +#: models.py:311 msgid "Disabled" msgstr "Désactivé" -#: models.py:257 +#: models.py:312 msgid "Imported" msgstr "Importé" -#: models.py:258 +#: models.py:313 msgid "Excluded" msgstr "Exclu" -#: models.py:260 +#: models.py:315 msgid "Status" msgstr "État" -#: models.py:261 +#: models.py:316 msgid "Import key" msgstr "Clé d'import" -#: models.py:263 +#: models.py:318 msgid "Import version" msgstr "Version de l'import" -#: models.py:268 templates/chimere/edit.html:56 +#: models.py:323 templates/chimere/edit.html:56 #: templates/chimere/edit_route.html:52 msgid "Start date" msgstr "Date de début" -#: models.py:269 +#: models.py:324 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:271 templates/chimere/edit.html:62 +#: models.py:326 templates/chimere/edit.html:62 #: templates/chimere/edit_route.html:58 msgid "End date" msgstr "Date de fin" -#: models.py:272 +#: models.py:327 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:304 +#: models.py:359 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:305 +#: models.py:360 msgid "Localisation" msgstr "Localisation" -#: models.py:307 +#: models.py:362 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:311 templates/chimere/edit.html:49 +#: models.py:366 templates/chimere/edit.html:49 #: templates/chimere/edit_route.html:46 msgid "Description" msgstr "Description" -#: models.py:382 models.py:1082 +#: models.py:420 models.py:1120 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:476 +#: models.py:514 msgid "Audio" msgstr "Audio" -#: models.py:477 +#: models.py:515 msgid "Video" msgstr "Vidéo" -#: models.py:479 +#: models.py:517 msgid "Other" msgstr "Autre" -#: models.py:480 +#: models.py:518 msgid "Media type" msgstr "Type de media" -#: models.py:483 +#: models.py:521 msgid "Mime type" msgstr "Type mime" -#: models.py:485 +#: models.py:523 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:489 +#: models.py:527 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:490 +#: models.py:528 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:525 +#: models.py:563 msgid "Extension name" -msgstr "" +msgstr "Nom de l'extension" -#: models.py:527 +#: models.py:565 msgid "Associated multimedia type" msgstr "Type de multimedia associé" -#: models.py:531 +#: models.py:569 msgid "Multimedia extension" msgstr "Extension de fichier multimedia" -#: models.py:532 +#: models.py:570 msgid "Multimedia extensions" msgstr "Extensions de fichier multimedia" -#: models.py:539 -msgid "Url" -msgstr "Url" - -#: models.py:542 models.py:587 +#: models.py:580 models.py:625 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:547 +#: models.py:585 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:589 +#: models.py:627 msgid "Thumbnail" msgstr "Miniature" -#: models.py:593 +#: models.py:631 msgid "Thumbnail height" msgstr "Hauteur de la miniature" -#: models.py:595 +#: models.py:633 msgid "Thumbnail width" msgstr "Largeur de la miniature" -#: models.py:604 +#: models.py:642 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:700 +#: models.py:738 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:701 +#: models.py:739 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:703 +#: models.py:741 msgid "KML" msgstr "KML" -#: models.py:703 +#: models.py:741 msgid "GPX" msgstr "GPX" -#: models.py:708 +#: models.py:746 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:709 +#: models.py:747 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:759 +#: models.py:797 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:763 +#: models.py:801 msgid "Associated file" msgstr "Fichier associé" -#: models.py:938 +#: models.py:976 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:944 +#: models.py:982 msgid "Layer" msgstr "Couche" -#: models.py:950 +#: models.py:988 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:952 templates/chimere/blocks/welcome.html:3 +#: models.py:990 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:956 +#: models.py:994 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:958 +#: models.py:996 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:960 +#: models.py:998 msgid "Default area" msgstr "Zone par défaut" -#: models.py:961 +#: models.py:999 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:965 +#: models.py:1003 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:967 +#: models.py:1005 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:968 +#: models.py:1006 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -514,76 +531,76 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:972 models.py:1039 +#: models.py:1010 models.py:1077 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:973 +#: models.py:1011 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:975 +#: models.py:1013 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:977 +#: models.py:1015 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:1024 +#: models.py:1062 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:1028 models.py:1029 +#: models.py:1066 models.py:1067 msgid "Layers" msgstr "Couches" -#: models.py:1037 +#: models.py:1075 msgid "Mandatory" msgstr "Obligatoire" -#: models.py:1040 +#: models.py:1078 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:1042 +#: models.py:1080 msgid "Text" msgstr "Texte" -#: models.py:1043 +#: models.py:1081 msgid "Long text" msgstr "Texte long" -#: models.py:1044 +#: models.py:1082 msgid "Password" msgstr "Mot de passe" -#: models.py:1046 +#: models.py:1084 msgid "Choices" msgstr "Choix" -#: models.py:1054 +#: models.py:1092 msgid "Type" msgstr "Type" -#: models.py:1059 models.py:1070 models.py:1084 +#: models.py:1097 models.py:1108 models.py:1122 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:1071 models.py:1085 +#: models.py:1109 models.py:1123 msgid "Value" msgstr "Valeur" -#: models.py:1077 +#: models.py:1115 msgid "Model property choice" msgstr "Choix pour les modèles de propriété" -#: models.py:1096 +#: models.py:1134 msgid "Property" msgstr "Propriété" @@ -683,19 +700,19 @@ msgstr "" msgid "Bad param" msgstr "Mauvais paramètre" -#: views.py:238 +#: views.py:241 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:320 +#: views.py:323 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:442 +#: views.py:455 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:445 +#: views.py:458 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." @@ -704,52 +721,52 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:449 +#: views.py:462 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:586 +#: views.py:620 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:718 +#: views.py:753 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:204 +#: widgets.py:229 msgid "Street, City, Country" msgstr "Rue, Commune, Pays" -#: widgets.py:270 +#: widgets.py:295 msgid "Latitude" msgstr "Latitude" -#: widgets.py:270 +#: widgets.py:295 msgid "Longitude" msgstr "Longitude" -#: widgets.py:295 +#: widgets.py:320 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:345 +#: widgets.py:370 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:346 +#: widgets.py:371 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:348 +#: widgets.py:373 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:349 +#: widgets.py:374 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:350 +#: widgets.py:375 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -757,7 +774,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:352 +#: widgets.py:377 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -765,17 +782,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:357 +#: widgets.py:382 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:358 +#: widgets.py:383 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:359 +#: widgets.py:384 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -783,7 +800,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:361 +#: widgets.py:386 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -792,33 +809,33 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:368 +#: widgets.py:393 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:371 +#: widgets.py:396 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:372 +#: widgets.py:397 msgid "or" msgstr "ou" -#: widgets.py:377 +#: widgets.py:402 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:400 +#: widgets.py:425 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:400 +#: widgets.py:425 msgid "Draw" msgstr "Tracer" -#: widgets.py:525 +#: widgets.py:550 msgid "Select..." msgstr "Sélectionner..." @@ -1068,6 +1085,11 @@ 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:47 +msgid "See it on the map" +msgstr "Voir sur la carte" + #: templates/chimere/blocks/routing.html:5 msgid "Itinerary" msgstr "Itinéraire" @@ -1128,10 +1150,6 @@ msgstr "Retourner à la carte" msgid "Welcome" msgstr "Accueil" -#: templates/chimere/blocks/welcome.html:47 -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" @@ -1164,3 +1182,6 @@ msgstr "Choisir une zone pré-définie" msgid "Or select the area by zooming and panning this map" msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" +#: templatetags/chimere_tags.py:64 +msgid "Welcome to the %s" +msgstr "Bienvenue sur %s" diff --git a/chimere/static/chimere/js/textareas-full.js b/chimere/static/chimere/js/textareas-full.js deleted file mode 100644 index 1200474..0000000 --- a/chimere/static/chimere/js/textareas-full.js +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2012 Étienne Loks - -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 . - -See the file COPYING for details. -*/ - -tinyMCE.init({ - mode : "textareas", - theme : "advanced", - editor_selector : "mceEditor", - relative_urls : false -}); -- cgit v1.2.3 From 9b843c1563690fc0975ec1dd8c39c638ed825576 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 5 Sep 2012 19:14:19 +0200 Subject: Add contact email var to main template --- chimere/views.py | 3 ++- example_project/settings.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/chimere/views.py b/chimere/views.py index a9b75a2..b504cae 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -135,7 +135,8 @@ def index(request, area_name=None, default_area=None, simple=False): 'areas_visible': settings.CHIMERE_DISPLAY_AREAS, 'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER, 'dynamic_categories':response_dct['dynamic_categories'], - 'zoomout':zoomout + 'zoomout':zoomout, + 'contact_email':settings.CONTACT_EMAIL }) tpl = 'chimere/main_map.html' if simple: diff --git a/example_project/settings.py b/example_project/settings.py index c878c88..f67ceeb 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -15,6 +15,7 @@ PROJECT_NAME = u'Chimère' ROOT_PATH = os.path.realpath(os.path.dirname(__file__)) + "/" EMAIL_HOST = 'localhost' +CONTACT_EMAIL = '' STATIC_URL = '/static/' STATIC_ROOT = ROOT_PATH + 'static/' -- cgit v1.2.3 From c2f01a7392ed26d2637d9e792702f146ef99e61a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 7 Sep 2012 11:26:54 +0200 Subject: Manage a category description --- chimere/admin.py | 4 +- chimere/forms.py | 6 + ...0034_auto__add_field_subcategory_description.py | 249 +++++++++++++++++++++ chimere/models.py | 13 +- chimere/urls.py | 2 + chimere/views.py | 10 + 6 files changed, 281 insertions(+), 3 deletions(-) create mode 100644 chimere/migrations/0034_auto__add_field_subcategory_description.py diff --git a/chimere/admin.py b/chimere/admin.py index 2125bef..e86bcea 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -35,7 +35,8 @@ except ImportError: pass from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ - NewsAdminForm, CategoryAdminForm, ImporterAdminForm, PageAdminForm + SubCategoryAdminForm, NewsAdminForm, CategoryAdminForm, ImporterAdminForm,\ + PageAdminForm from chimere.models import Category, Icon, SubCategory, Marker, \ PropertyModel, News, Route, Area, ColorTheme, Color, RouteFile,\ MultimediaType, MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ @@ -164,6 +165,7 @@ class SubCategoryAdmin(admin.ModelAdmin): """ list_display = ('name', 'category', 'available') list_filter = ('category',) + form = SubCategoryAdminForm def importing(modeladmin, request, queryset): for importer in queryset: diff --git a/chimere/forms.py b/chimere/forms.py index a5ad894..7315775 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -95,6 +95,12 @@ 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 diff --git a/chimere/migrations/0034_auto__add_field_subcategory_description.py b/chimere/migrations/0034_auto__add_field_subcategory_description.py new file mode 100644 index 0000000..c77ab1d --- /dev/null +++ b/chimere/migrations/0034_auto__add_field_subcategory_description.py @@ -0,0 +1,249 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'SubCategory.description' + db.add_column('chimere_subcategory', 'description', + self.gf('django.db.models.fields.TextField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'SubCategory.description' + db.delete_column('chimere_subcategory', 'description') + + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}), + 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'restrict_to_extent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'db_table': "'chimere_subcategory_areas'", 'to': "orm['chimere.SubCategory']"}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'blank': 'True'}), + 'welcome_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.arealayers': { + 'Meta': {'ordering': "('order',)", 'object_name': 'AreaLayers'}, + 'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Area']"}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Layer']"}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.color': { + 'Meta': {'ordering': "['order']", 'object_name': 'Color'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.colortheme': { + 'Meta': {'object_name': 'ColorTheme'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.icon': { + 'Meta': {'object_name': 'Icon'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.importer': { + 'Meta': {'object_name': 'Importer'}, + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'chimere.layer': { + 'Meta': {'object_name': 'Layer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'point': ('chimere.widgets.PointField', [], {}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.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']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'chimere.multimediatype': { + 'Meta': {'object_name': 'MultimediaType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'content': ('django.db.models.fields.TextField', [], {}), + 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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', [], {}), + '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', [], {}) + }, + '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'}), + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'}, + 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.subcategory': { + 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] \ No newline at end of file diff --git a/chimere/models.py b/chimere/models.py index dabe9fd..8e8fc0f 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -214,6 +214,7 @@ class SubCategory(models.Model): ('R', _(u'Route')), ('B', _(u'Both')),) item_type = models.CharField(_(u"Item type"), max_length=1, choices=TYPE) + description = models.TextField(blank=True, null=True) def __unicode__(self): return u"%s / %s" % (self.category.name, self.name) class Meta: @@ -259,6 +260,16 @@ class SubCategory(models.Model): [(subcat.pk, subcat.name) for subcat in subcats])) return cats + def getJSON(self, categories_id=[]): + '''Return a JSON string - mainly used to get description + ''' + items = {'id':self.pk, 'name':json.dumps(self.name), + 'description':json.dumps(self.description) if self.description\ + else ''} + json_string = u'{"pk": %(id)d, "name": %(name)s, '\ + u'"description":"%(description)s"}' % items + return json_string + IMPORTERS = {'KML':KMLManager, 'OSM':OSMManager, 'SHP':ShapefileManager @@ -615,7 +626,6 @@ def multimediafile_post_save(sender, **kwargs): multimediafile.save() post_save.connect(multimediafile_post_save, sender=MultimediaFile) - class PictureFile(models.Model): name = models.CharField(_(u"Name"), max_length=150) picture = models.ImageField(_(u"Image"), upload_to='pictures', @@ -647,7 +657,6 @@ def scale_image(max_x, pair): new_y = (float(max_x) / x) * y return (int(max_x), int(new_y)) - IMAGE_EXIF_ORIENTATION_MAP = { 1: 0, 8: 2, diff --git a/chimere/urls.py b/chimere/urls.py index 086be3f..35b08d0 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -83,6 +83,8 @@ urlpatterns += patterns('chimere.views', name="getgeoobjects"), url(r'^(?P[a-zA-Z0-9_-]+/)?getAvailableCategories/$', 'get_available_categories', name="get_categories"), + url(r'^(?P[a-zA-Z0-9_-]+/)?get-category/(?P\d+)/?$', + 'getCategory', name="get_category"), url(r'^(?P[a-zA-Z0-9_-]*/)?ty/(?P\w+)$', 'redirectFromTinyURN', name="tiny"), url(r'^(?P[a-zA-Z0-9_-]+/)?upload_file/((?P\w+)/)?$', diff --git a/chimere/views.py b/chimere/views.py index b504cae..ecaae0b 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -642,6 +642,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 -- cgit v1.2.3 From db7e03b793d5e5277048ca919404719814c027b1 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 7 Sep 2012 14:42:03 +0200 Subject: Manage subcategory description --- chimere/models.py | 2 +- chimere/static/chimere/css/styles.css | 4 +- chimere/static/chimere/js/jquery.chimere.js | 60 ++++++++++++++++++++++++----- chimere/templates/chimere/main_map.html | 7 +++- chimere/urls.py | 2 +- 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/chimere/models.py b/chimere/models.py index 8e8fc0f..d51cd5b 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -267,7 +267,7 @@ class SubCategory(models.Model): 'description':json.dumps(self.description) if self.description\ else ''} json_string = u'{"pk": %(id)d, "name": %(name)s, '\ - u'"description":"%(description)s"}' % items + u'"description":%(description)s}' % items return json_string IMPORTERS = {'KML':KMLManager, diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 454480a..df3743d 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -92,7 +92,7 @@ div.warning, opacity:0.9; } -#panel, #areas, #detail, #category_detail, #chimere_itinerary_panel{ +#panel, #areas, #detail, #category_description, #chimere_itinerary_panel{ opacity:0.8; } @@ -115,7 +115,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; diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 6a8dbed..3a067f2 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -376,7 +376,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } }); }, - /* * Update the categories div in ajax */ @@ -440,15 +439,37 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { * Add event listener in categories DOM elements */ $('#categories #ul_categories > li > input').bind("click", function () { - _toggle_subcategories($(this));methods.loadGeoObjects();settings.permalink.updateLink();}); + _toggle_subcategories($(this)); + methods.loadGeoObjects(); + settings.permalink.updateLink(); + }); $('.subcategories li input').bind("click", function () { - methods.loadGeoObjects();_toggle_categories($(this));settings.permalink.updateLink();}); + if($(this).is(':checked')){ + var c_name = $(this).attr('name'); + methods.subcategory_detail( + c_name.substr(c_name.lastIndexOf("_")+1)); + } + methods.loadGeoObjects(); + _toggle_categories($(this)); + settings.permalink.updateLink(); + }); $('#display_submited_check').bind("click", function () { - methods.loadGeoObjects();settings.permalink.updateLink();}); + 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").bind("click", function (e) { + var id = this.id.substr(this.id.lastIndexOf("_")+1); + methods.toggle_category(id); + }); } var _reCheckCategories = function (){ /* recheck categories on init or when a redraw occurs */ @@ -754,7 +775,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.current_itinerary_number = 0; settings.current_route_feature = null; }, - // display a route route: function(){ if($('#search_routing').length) $('#search_routing').button('enable'); @@ -883,12 +903,32 @@ 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 diff --git a/chimere/templates/chimere/main_map.html b/chimere/templates/chimere/main_map.html index 9f220b5..a0ecffc 100644 --- a/chimere/templates/chimere/main_map.html +++ b/chimere/templates/chimere/main_map.html @@ -18,6 +18,12 @@ +
    +
    + +
    {% if areas_visible %} {% display_areas %} @@ -28,7 +34,6 @@
    -
    {% endblock %} {% block content %} {{block.super}} diff --git a/chimere/urls.py b/chimere/urls.py index 35b08d0..2e40a5d 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -83,7 +83,7 @@ urlpatterns += patterns('chimere.views', name="getgeoobjects"), url(r'^(?P[a-zA-Z0-9_-]+/)?getAvailableCategories/$', 'get_available_categories', name="get_categories"), - url(r'^(?P[a-zA-Z0-9_-]+/)?get-category/(?P\d+)/?$', + url(r'^(?P[a-zA-Z0-9_-]+/)?getCategory/(?P\d+)/?$', 'getCategory', name="get_category"), url(r'^(?P[a-zA-Z0-9_-]*/)?ty/(?P\w+)$', 'redirectFromTinyURN', name="tiny"), -- cgit v1.2.3 From 1be7301bc14fd2bd44e758662e1f4254f4bf7181 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 8 Sep 2012 20:07:39 +0200 Subject: Add a print css --- chimere/static/chimere/css/print.css | 36 ++++++++++++++++++++++++++++++++++++ chimere/templates/chimere/base.html | 1 + 2 files changed, 37 insertions(+) create mode 100644 chimere/static/chimere/css/print.css diff --git a/chimere/static/chimere/css/print.css b/chimere/static/chimere/css/print.css new file mode 100644 index 0000000..b6b4e68 --- /dev/null +++ b/chimere/static/chimere/css/print.css @@ -0,0 +1,36 @@ +#topbar, +#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; +} + + + diff --git a/chimere/templates/chimere/base.html b/chimere/templates/chimere/base.html index 709ff9c..e4d514a 100644 --- a/chimere/templates/chimere/base.html +++ b/chimere/templates/chimere/base.html @@ -2,6 +2,7 @@ {% load chimere_tags i18n %} {% block extra_head %} + {% if css_area %} {% endif %} {% endblock %} -- cgit v1.2.3 From 8b473eef82deaaaee340d045e3be09263bfbc7bb Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 9 Sep 2012 12:42:37 +0200 Subject: Changes on "Share network" - add a printer icon - fix permalink --- chimere/static/chimere/css/styles.css | 4 ++++ chimere/static/chimere/img/images_licences | 3 ++- chimere/static/chimere/img/printer.png | Bin 0 -> 914 bytes chimere/static/chimere/img/share-icon.png | Bin 0 -> 2148 bytes chimere/static/chimere/img/share-icon.xcf | Bin 0 -> 5431 bytes chimere/static/chimere/js/jquery.chimere.js | 24 +++++++++++++----------- chimere/views.py | 28 +++++++++++++++++++--------- 7 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 chimere/static/chimere/img/printer.png create mode 100644 chimere/static/chimere/img/share-icon.png create mode 100644 chimere/static/chimere/img/share-icon.xcf diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index df3743d..001fa7b 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -347,6 +347,10 @@ ul.share li{ height:22px; } +.share .share-icon img{ + width:74px; +} + .detail_footer{ text-align:center; position:absolute; diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index cbc9307..d6d2773 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -22,7 +22,8 @@ Url: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg 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 (8thNote.png) diff --git a/chimere/static/chimere/img/printer.png b/chimere/static/chimere/img/printer.png new file mode 100644 index 0000000..5a5dbaf Binary files /dev/null and b/chimere/static/chimere/img/printer.png differ diff --git a/chimere/static/chimere/img/share-icon.png b/chimere/static/chimere/img/share-icon.png new file mode 100644 index 0000000..89b631c Binary files /dev/null and b/chimere/static/chimere/img/share-icon.png differ diff --git a/chimere/static/chimere/img/share-icon.xcf b/chimere/static/chimere/img/share-icon.xcf new file mode 100644 index 0000000..d149768 Binary files /dev/null and b/chimere/static/chimere/img/share-icon.xcf differ diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 3a067f2..d7da137 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -591,9 +591,10 @@ 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); - settings.map.setCenter(feature.lonlat, 16); + _repan_popup(); methods.loadCategories(); } return feature; @@ -864,22 +865,23 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { uri += "getDetail/" + pk; var params = {} if (settings.simple) { params["simple"] = 1; } - $.ajax({url: uri, + $.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.popupContentFull) { - $('#detail').html(data).show(); - } - else { - settings.current_popup.setContentHTML("
    " + data + "
    "); - } + settings.current_popup.setContentHTML("
    " + data + "
    "); } } + } }); }, center_on_feature: function(feature) { diff --git a/chimere/views.py b/chimere/views.py index ecaae0b..20b4bd2 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -104,6 +104,21 @@ def get_base_response(area_name=""): base_response_dct['JQUERY_CSS_URLS'] = settings.JQUERY_CSS_URLS return base_response_dct, None +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): """ Main page @@ -116,7 +131,6 @@ def index(request, area_name=None, default_area=None, simple=False): request.session['last_visit'] != today: request.session['last_visit'] = today news_visible = True - news_visible = True response_dct, redir = get_base_response(area_name) if redir: return redir @@ -138,6 +152,8 @@ def index(request, area_name=None, default_area=None, simple=False): 'zoomout':zoomout, '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' @@ -507,15 +523,9 @@ 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'] = ";".join(getStaffEmails()) if net_dct['to']: net_dct["body"] = _(settings.CHIMERE_MODIF_EMAIL) -- cgit v1.2.3 From add49610829534e6d059f53ec8240ef5f2c9fea1 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 9 Sep 2012 23:51:25 +0200 Subject: Manage itinerary in permalink --- chimere/static/chimere/js/jquery.chimere.js | 51 +++++++++++++++++++++++- chimere/templates/chimere/blocks/map_params.html | 4 ++ chimere/templatetags/chimere_tags.py | 3 +- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index d7da137..68a621e 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -67,6 +67,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 @@ -155,8 +160,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; } @@ -267,6 +293,27 @@ 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(); + } + } }, // end of init activateContextMenu: function(){ @@ -775,6 +822,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { settings.routing_steps = new Array(); settings.current_itinerary_number = 0; settings.current_route_feature = null; + settings.permalink.updateLink(); }, // display a route route: function(){ @@ -806,6 +854,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { } uri += step.lon + '_' + step.lat; } + settings.permalink.updateLink(); $.ajax({url: uri, dataType: "json", success: function (data) { diff --git a/chimere/templates/chimere/blocks/map_params.html b/chimere/templates/chimere/blocks/map_params.html index 27762a3..c4150da 100644 --- a/chimere/templates/chimere/blocks/map_params.html +++ b/chimere/templates/chimere/blocks/map_params.html @@ -15,6 +15,10 @@ {% 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 %} chimere_init_options["icon_offset"] = new OpenLayers.Pixel({{icon_offset_x}}, {{icon_offset_y}}); chimere_init_options["dynamic_categories"] = {{ dynamic_categories }}; diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 2e5e1fe..88827a8 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -219,7 +219,8 @@ bounds.extend(new OpenLayers.LonLat(%f, %f)); # Default values 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: -- cgit v1.2.3 From d29dbe491aec00f708a8a66223159784db2feaf3 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 9 Sep 2012 23:53:49 +0200 Subject: Fix on itinerary permalink --- chimere/templates/chimere/blocks/map_params.html | 1 + 1 file changed, 1 insertion(+) diff --git a/chimere/templates/chimere/blocks/map_params.html b/chimere/templates/chimere/blocks/map_params.html index c4150da..2247c06 100644 --- a/chimere/templates/chimere/blocks/map_params.html +++ b/chimere/templates/chimere/blocks/map_params.html @@ -19,6 +19,7 @@ {% 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 }}; -- cgit v1.2.3 From 1fd24bbf91a2c7f0e8f83e8c06c27fc5b0cb0f9a Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 10 Sep 2012 17:33:59 +0200 Subject: Manage share toolbar inside a template tag --- chimere/templates/chimere/blocks/share_bar.html | 39 +++++++++++++++++++++++++ chimere/templates/chimere/detail.html | 11 ++----- chimere/templatetags/chimere_tags.py | 9 ++++++ chimere/urls.py | 2 ++ chimere/views.py | 13 ++++++++- 5 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 chimere/templates/chimere/blocks/share_bar.html 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 %} + {{share_network.0}} + {% endfor %}{%else%} + {% endif %} + + {% endif %} diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html index 2bd55aa..94270cb 100644 --- a/chimere/templates/chimere/detail.html +++ b/chimere/templates/chimere/detail.html @@ -25,21 +25,14 @@ {% if marker.multimedia_items %} {% trans "Show multimedia gallery" %} {% endif %} - {% if share_networks %} - {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %} - {{share_network.0}} - {% endfor %}{%else%} - {% endif %} + + {% share_bar marker.name %} {% trans "Propose a modification" %} {% comment %} {% trans "Submit a modification" %} {% endcomment %} -{% endif %} {% if marker.multimedia_items %}