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 --- example_project/settings.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'example_project') 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 (limited to 'example_project') 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 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 (limited to 'example_project') 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 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(-) (limited to 'example_project') 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 (limited to 'example_project') 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%} -