summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoretienne <etienne@9215b0d5-fb2c-4bbd-8d3e-bd2e9090e864>2009-01-11 13:16:21 +0000
committeretienne <etienne@9215b0d5-fb2c-4bbd-8d3e-bd2e9090e864>2009-01-11 13:16:21 +0000
commit03c7e15227fb84b94d9f870aac69d7d54b61889a (patch)
treec7d4c5e276fd3092449c195b8c354f7ebe645979
parent4182d638dcbe194b65b38d1ae92068dadbefc84d (diff)
downloadChimère-03c7e15227fb84b94d9f870aac69d7d54b61889a.tar.bz2
Chimère-03c7e15227fb84b94d9f870aac69d7d54b61889a.zip
Modification of created routes
git-svn-id: http://www.peacefrogs.net/svn/chimere/trunk@9 9215b0d5-fb2c-4bbd-8d3e-bd2e9090e864
-rw-r--r--main/actions.py3
-rw-r--r--main/admin.py15
-rw-r--r--main/forms.py70
-rw-r--r--main/models.py74
-rw-r--r--main/views.py41
-rw-r--r--main/widgets.py81
-rw-r--r--static/forms.css40
-rw-r--r--static/styles.css5
-rw-r--r--urls.py1
9 files changed, 319 insertions, 11 deletions
diff --git a/main/actions.py b/main/actions.py
index d47a323..a4bf06d 100644
--- a/main/actions.py
+++ b/main/actions.py
@@ -29,4 +29,5 @@ class Action:
def __init__(self, id, path, label):
self.id, self.path, self.label = id, main_path + path, label
-actions = [Action('view', '', _('View')), Action('edit', 'edit', _('Add'))]
+actions = [Action('view', '', _('View')), Action('edit', 'edit', _('Add')),
+ Action('edit-route', 'edit-route', _('Add route'))]
diff --git a/main/admin.py b/main/admin.py
index 7e19e4b..21ba3cb 100644
--- a/main/admin.py
+++ b/main/admin.py
@@ -22,8 +22,8 @@ Settings for administration pages
"""
from chimere.main.models import Category, Icon, SubCategory, Marker, \
- PropertyModel, Property, News
-from chimere.main.forms import MarkerAdminForm
+ PropertyModel, Property, News, Route
+from chimere.main.forms import MarkerAdminForm, RouteAdminForm
from django.contrib import admin
class MarkerAdmin(admin.ModelAdmin):
@@ -35,6 +35,16 @@ class MarkerAdmin(admin.ModelAdmin):
list_filter = ('status', 'subcategory')
form = MarkerAdminForm
+
+class RouteAdmin(admin.ModelAdmin):
+ """
+ Specialized the Route field.
+ """
+ search_fields = ("name",)
+ list_display = ('name', 'subcategory', 'status')
+ list_filter = ('status', 'subcategory')
+ form = RouteAdminForm
+
class SubCategoryAdmin(admin.ModelAdmin):
"""
Specialized the subcategory admin
@@ -48,5 +58,6 @@ admin.site.register(Icon)
admin.site.register(Category)
admin.site.register(SubCategory, SubCategoryAdmin)
admin.site.register(Marker, MarkerAdmin)
+admin.site.register(Route, RouteAdmin)
admin.site.register(PropertyModel)
admin.site.register(Property)
diff --git a/main/forms.py b/main/forms.py
index cb45edc..2343869 100644
--- a/main/forms.py
+++ b/main/forms.py
@@ -23,7 +23,7 @@ Forms
from django import forms
from django.contrib.gis.db import models
-from chimere.main.models import Marker, PropertyModel, Property
+from chimere.main.models import Marker, Route, PropertyModel, Property
class MarkerAdminForm(forms.ModelForm):
"""
@@ -92,3 +92,71 @@ class MarkerForm(MarkerAdminForm):
class Meta:
model = Marker
exclude = ('status',)
+
+class RouteAdminForm(forms.ModelForm):
+ """
+ Main form for route
+ """
+ # declare properties
+ for property in PropertyModel.objects.filter(available=True):
+ exec('property_%d_%d = forms.CharField(label="%s", widget=forms.%s, \
+required=False)' % (property.order, property.id, property.name,
+ PropertyModel.TYPE_WIDGET[property.type]))
+ class Meta:
+ model = Route
+
+ def __init__(self, *args, **keys):
+ """
+ Custom initialization method in order to manage properties
+ """
+ if 'instance' in keys and keys['instance']:
+ instance = keys['instance']
+ property_dct = {}
+ for pm in PropertyModel.objects.filter(available=True):
+ property = instance.getProperty(pm)
+ if property:
+ property_dct[pm.getNamedId()] = property.value
+ if 'initial' in keys:
+ keys['initial'].update(property_dct)
+ else:
+ keys['initial'] = property_dct
+ super(RouteAdminForm, self).__init__(*args, **keys)
+
+ def save(self, *args, **keys):
+ """
+ Custom save method in order to manage associeted properties
+ """
+ new_marker = super(RouteAdminForm, self).save(*args, **keys)
+ if 'status' not in self.cleaned_data:
+ new_marker.status = 'S'
+ new_marker.save()
+ # save each property
+ for propertymodel in PropertyModel.objects.filter(available=True):
+ properties = Property.objects.filter(marker=new_marker,
+ propertymodel=propertymodel)
+ # new property
+ if not properties:
+ new_property = Property.objects.create(marker=new_marker,
+ propertymodel=propertymodel,
+ value=self.cleaned_data['property_%d_%d' % (
+ propertymodel.order, propertymodel.id)])
+ new_property.save()
+ else:
+ # in case of multiple edition as the same time delete arbitrary
+ # the others
+ if len(properties) > 1:
+ for property in properties[1:]:
+ property.delete()
+ property = properties[0]
+ property.value = self.cleaned_data['property_%d_%d' % (
+ propertymodel.order, propertymodel.id)]
+ property.save()
+ return new_marker
+
+class RouteForm(RouteAdminForm):
+ """
+ Form for the edit page
+ """
+ class Meta:
+ model = Route
+ exclude = ('status',)
diff --git a/main/models.py b/main/models.py
index f449d09..ead8a85 100644
--- a/main/models.py
+++ b/main/models.py
@@ -26,7 +26,7 @@ from django.contrib.gis.db import models
from django.contrib import admin
from chimere import settings
-from chimere.main.widgets import PointField
+from chimere.main.widgets import PointField, RouteField
class News(models.Model):
@@ -163,6 +163,78 @@ class Marker(models.Model):
'icon_width':self.subcategory.icon.image.width,
'icon_height':self.subcategory.icon.image.height,}
+class Route(models.Model):
+ '''Route on the map
+ '''
+ name = models.CharField(_("Name"), max_length=150)
+ subcategory = models.ForeignKey(SubCategory, verbose_name=_("Subcategory"))
+ route = RouteField(_("Route"))
+ picture = models.ImageField(_("Image"), upload_to='upload', blank=True,
+ height_field='height', width_field='width')
+ STATUS = (('S', _('Submited')),
+ ('A', _('Available')),
+ ('D', _('Disabled')),)
+ STATUS_DCT = {}
+ for key, label in STATUS:
+ STATUS_DCT[key] = label
+ status = models.CharField(_("Status"), max_length=1, choices=STATUS)
+ objects = models.GeoManager()
+
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ ordering = ('subcategory__category', 'subcategory', 'status', 'name')
+ verbose_name = _("Route")
+
+ def getLatitude(self):
+ '''Return the latitude
+ '''
+ return self.point.y
+
+ def getLongitude(self):
+ '''Return the longitude
+ '''
+ return self.point.x
+
+ def getProperty(self, propertymodel, safe=None):
+ """Get the property of an associated property model.
+ If safe set to True, verify if the property is available
+ """
+ if safe and not propertymodel.available:
+ return
+ try:
+ property = Property.objects.get(propertymodel=propertymodel,
+ marker=self)
+ except Property.DoesNotExist:
+ return
+ return property
+
+ def getProperties(self):
+ """Get all the property availables
+ """
+ properties = []
+ for pm in PropertyModel.objects.filter(available=True):
+ property = self.getProperty(pm)
+ if property:
+ properties.append(property)
+ return properties
+
+ def getGeoJSON(self):
+ '''Return a GeoJSON string
+ '''
+ return """{"type":"Feature", "geometry":{"type":"Point", \
+"crs": "EPSG:%(epsg)d", "coordinates":[%(longitude)s, %(latitude)s]}, \
+"properties":{"pk": %(id)d, "name": "%(name)s", \
+"icon_path":"%(icon_path)s", "icon_width":%(icon_width)d, \
+"icon_height":%(icon_height)d}}""" % {'id':self.id, 'name':self.name,
+'icon_path':self.subcategory.icon.image, 'latitude':self.getLatitude(),
+'longitude':self.getLongitude(), 'epsg':settings.EPSG_PROJECTION,
+'icon_width':self.subcategory.icon.image.width,
+'icon_height':self.subcategory.icon.image.height,}
+
+
+
class PropertyModel(models.Model):
'''Model for a property
'''
diff --git a/main/views.py b/main/views.py
index d655aad..f0cc604 100644
--- a/main/views.py
+++ b/main/views.py
@@ -30,9 +30,10 @@ from django.core import serializers
from chimere import settings
from chimere.main.actions import actions
-from chimere.main.models import SubCategory, PropertyModel, Marker, News
-from chimere.main.widgets import getMapJS, PointChooserWidget, URL_OSM_JS
-from chimere.main.forms import MarkerForm
+from chimere.main.models import SubCategory, PropertyModel, Marker, Route, News
+from chimere.main.widgets import getMapJS, PointChooserWidget, \
+ RouteChooserWidget, URL_OSM_JS
+from chimere.main.forms import MarkerForm, RouteForm
def index(request):
"""
@@ -96,6 +97,40 @@ def edit(request):
response_dct['current_category'] = int(form.data['subcategory'])
return render_to_response('edit.html', response_dct)
+def editRoute(request):
+ """
+ Route edition page
+ """
+ # If the form has been submited
+ if request.method == 'POST':
+ form = RouteForm(request.POST, request.FILES)
+ print request.POST
+ # All validation rules pass
+ if form.is_valid():
+ route = form.save()
+ # set the submited status
+ route.status = 'S'
+ route.save()
+ return HttpResponseRedirect('/chimere/submited')
+ else:
+ # An unbound form
+ form = RouteForm()
+ # get the « manualy » declared_fields. Ie: properties
+ declared_fields = form.declared_fields.keys()
+ response_dct = {'actions':actions, 'action_selected':'edit-route',
+ 'error_message':'',
+ 'media_path':settings.MEDIA_URL,
+ 'form':form,
+ 'extra_head':form.media,
+ 'sub_categories':SubCategory.getAvailable(),
+ 'route_widget':RouteChooserWidget().render('route', None),
+ 'properties':declared_fields
+ }
+ # manualy populate the custom widget
+ if 'subcategory' in form.data and form.data['subcategory']:
+ response_dct['current_category'] = int(form.data['subcategory'])
+ return render_to_response('edit_route.html', response_dct)
+
def welcome(request, display=None):
"""
Welcome string
diff --git a/main/widgets.py b/main/widgets.py
index bd0a72b..1e12c19 100644
--- a/main/widgets.py
+++ b/main/widgets.py
@@ -23,7 +23,7 @@ Extra widgets and fields
from django import forms
from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ugettext as _
from chimere import settings
from django.contrib.gis.db import models
@@ -112,3 +112,82 @@ class PointField(models.PointField):
defaults = {'widget': PointChooserWidget}
keys.update(defaults)
return super(PointField, self).formfield(**keys)
+
+class RouteChooserWidget(forms.TextInput):
+ """
+ Manage the edition of route on a map
+ """
+ class Media:
+ css = {
+ "all": ("%sforms.css" % settings.MEDIA_URL,)
+ }
+ js = ["%sedit_route_map.js" % settings.MEDIA_URL] + URL_OSM_JS
+
+ def render(self, name, value, attrs=None):
+ '''
+ Render a map and latitude, longitude information field
+ '''
+ tpl = getMapJS()
+ help_create = ''
+ if not value:
+ help_create = """<h3>%s</h3>
+<p>%s</p>
+<p>%s</p>
+<p>%s</p>
+<p>%s</p>
+<p>%s</p>""" % (_("Creation mode"),
+_("To start drawing the route click on the toggle button : \"Start drawing\"."),
+_("Then click on the map to begin the drawing."),
+_("You can add points by clicking again."),
+_("To finish the drawing double click. When the drawing is finished you can \
+edit it."),
+_("While creating to undo a drawing click again on the toggle button \"Stop \
+drawing\"."))
+ help_modify = """<h3>%s</h3>
+<p>%s</p>
+<p>%s</p>
+<p>%s</p>""" % (_("Modification mode"),
+_("To move a point click on it and drag it to the desired position."),
+_("To delete a point move the mouse cursor over it and press the \"d\" key."),
+_("To add a point click in the middle of a segment and drag the new point to \
+the desired position"))
+ tpl += u'<script src="%sedit_route_map.js"></script>\n' % \
+ settings.MEDIA_URL
+ if not value:
+ tpl += u"""<div id='draw-toggle-off' class='toggle-button' \
+onclick='toggleDrawOn();'>%s</div>
+<div id='draw-toggle-on' class='toggle-button' \
+onclick='toggleDrawOff();'>%s</div>
+<hr class='spacer'/>""" % (_("Start drawing"), _("Stop drawing"))
+ tpl += """
+<div id='map_edit'></div>"""
+ if not value:
+ tpl += '''
+<div class='help-route' id='help-route-create'>%s</div>''' % help_create
+ style = ''
+ if value:
+ style = " style='display:block'"
+ tpl += """
+<div class='help-route' id='help-route-modify'%s>%s</div>
+<hr class='spacer'/>
+<input type='hidden' name='%s' id='id_%s' value="%s"/>
+""" % (style, help_modify, name, name, value)
+ tpl += """<script type='text/javascript'><!--
+init();"""
+ if value:
+ tpl += """
+var geometry='%s';
+initFeature(geometry);""" % value.json
+ tpl += """
+// --></script>
+"""
+ return mark_safe(tpl)
+
+class RouteField(models.LineStringField):
+ '''
+ Set the widget for the form field
+ '''
+ def formfield(self, **keys):
+ defaults = {'widget': RouteChooserWidget}
+ keys.update(defaults)
+ return super(RouteField, self).formfield(**keys)
diff --git a/static/forms.css b/static/forms.css
index e536e96..c8e4939 100644
--- a/static/forms.css
+++ b/static/forms.css
@@ -8,4 +8,42 @@ float:left;
#live_lonlat{
margin:1em;
float:left;
-} \ No newline at end of file
+}
+
+.toggle-button{
+float:left;
+padding:4px;
+-moz-border-radius: 4px;
+-webkit-border-radius: 4px;
+border-radius: 4px;
+border:1px solid grey;
+}
+
+#draw-toggle-off{
+color:black;
+}
+
+#draw-toggle-on{
+background-color:lightgrey;
+display:None;
+}
+
+.help-route{
+width:700px;
+background-color:#EEF;;
+margin: 10px 0px;
+float:left;
+padding:0 4px;
+-moz-border-radius: 4px;
+-webkit-border-radius: 4px;
+border-radius: 4px;
+border:1px solid grey;
+}
+
+#help-route-create{
+}
+
+#help-route-modify{
+display:None
+}
+
diff --git a/static/styles.css b/static/styles.css
index 28af34c..fda1fa9 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -41,6 +41,7 @@ color:purple;
hr.spacer{
clear:both;
border:None;
+visibility: hidden;
}
.edit label{
@@ -120,7 +121,7 @@ z-index:5;
top:50px;
bottom:58px;
left:80px;
-right:360px;
+margin-right:360px;
background-color:#FFF;
opacity:0.9;
-moz-border-radius:10px;
@@ -170,6 +171,8 @@ border: 1px solid black;
margin:0px;
padding:0px;
height:92%;
+margin:0;
+padding:0;
top:40px;
bottom:8px;
left:8px;
diff --git a/urls.py b/urls.py
index 62f476c..bfebc0d 100644
--- a/urls.py
+++ b/urls.py
@@ -13,6 +13,7 @@ urlpatterns = patterns('',
(r'^chimere/admin/(.*)', admin.site.root),
(r'^chimere/$', 'chimere.main.views.index'),
(r'^chimere/edit/$', 'chimere.main.views.edit'),
+ (r'^chimere/edit-route/$', 'chimere.main.views.editRoute'),
(r'^chimere/submited/$', 'chimere.main.views.submited'),
(r'^chimere/getDetail/(?P<marker_id>\d+)/$',
'chimere.main.views.getDetail'),