summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@proxience.com>2015-04-19 22:52:43 +0200
committerÉtienne Loks <etienne.loks@proxience.com>2015-04-19 22:52:43 +0200
commit5953bfdb54bd36f716d7b36681aae2648e3c1028 (patch)
treeae14b6fc6184b32030e1ab5ede8eceae0e00317f
parent908744a6f3d5ac40a48f0a52c5167e131785b2cc (diff)
downloadChimère-5953bfdb54bd36f716d7b36681aae2648e3c1028.tar.bz2
Chimère-5953bfdb54bd36f716d7b36681aae2648e3c1028.zip
Add a directory with all available markers
-rw-r--r--chimere/actions.py13
-rw-r--r--chimere/models.py9
-rw-r--r--chimere/settings.sample.py2
-rw-r--r--chimere/static/chimere/css/styles.css14
-rw-r--r--chimere/templates/chimere/category_directory.html35
-rw-r--r--chimere/templates/chimere/category_directory_detail.html25
-rw-r--r--chimere/templates/chimere/category_item_detail.html38
-rw-r--r--chimere/urls.py7
-rw-r--r--chimere/views.py154
9 files changed, 266 insertions, 31 deletions
diff --git a/chimere/actions.py b/chimere/actions.py
index 8ef5338..5ed3070 100644
--- a/chimere/actions.py
+++ b/chimere/actions.py
@@ -22,7 +22,7 @@ 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.core.urlresolvers import reverse, NoReverseMatch
from django.utils.translation import ugettext_lazy as _
from models import Page
@@ -33,7 +33,12 @@ class Action:
self.extra_url_args, self.url = extra_url_args, None
def update_url(self, area_name):
- self.url = reverse(self.path,
+ try:
+ self.url = reverse(self.path,
+ args=[area_name if area_name else ''] + self.extra_url_args)
+ except NoReverseMatch:
+ # backward url management
+ self.url = reverse(self.path,
args=[area_name + '/' if area_name else ''] + self.extra_url_args)
default_actions = [(Action('view', 'chimere:index', _('View')), []),
@@ -42,6 +47,10 @@ default_actions = [(Action('view', 'chimere:index', _('View')), []),
Action('edit-route', 'chimere:editroute', _('Add a new route'))),
),]
+if settings.CHIMERE_DIRECTORY:
+ default_actions.append((Action('categories', 'chimere:category-directory',
+ _('Directory')), []))
+
if settings.CHIMERE_FEEDS:
default_actions.append((Action('rss', 'chimere:feeds-form',
_('RSS feeds')), []))
diff --git a/chimere/models.py b/chimere/models.py
index fcc01a1..2469493 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -301,6 +301,14 @@ class SubCategory(models.Model):
json_string = json.dumps(self.getJSONDict())
return json_string
+ @property
+ def slug(self):
+ return defaultfilters.slugify(self.name)
+
+ @property
+ def item_nb(self):
+ return Marker.objects.filter(categories=self).count()
+
IMPORTERS = {'KML':KMLManager,
'OSM':OSMManager,
'SHP':ShapefileManager,
@@ -702,7 +710,6 @@ class Marker(GeographicItem):
url = reverse('chimere:tiny', args=[area_name, urn])
return url
-
PRE_ATTRS = {
'Marker':('name', 'geometry', 'import_version', 'modified_since_import'),
'Route':('name', 'geometry', 'import_version', 'modified_since_import'),
diff --git a/chimere/settings.sample.py b/chimere/settings.sample.py
index adb76fe..f6cc0b3 100644
--- a/chimere/settings.sample.py
+++ b/chimere/settings.sample.py
@@ -58,6 +58,8 @@ CHIMERE_DAYS_BEFORE_EVENT = 30
CHIMERE_ALL_DATED_ARE_FRONT = False
# allow feeds
CHIMERE_FEEDS = True
+# display a directory of items
+CHIMERE_DIRECTORY = False
CHIMERE_ICON_WIDTH = 21
CHIMERE_ICON_HEIGHT = 25
diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css
index 73b702f..9ae66ed 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -476,6 +476,11 @@ ul.share li{
margin:0;
}
+span.icon{
+ display:inline-block;
+ width:70px;
+}
+
#frm_categories{
padding:0;
margin:0;
@@ -1105,6 +1110,15 @@ div.pp_default .pp_expand{
padding:0 6px;
}
+#category-directory ul{
+ padding:0;
+}
+
+.category-directory-category{
+ font-variant: small-caps;
+ font-weight: bold;
+}
+
.olControlSimplePanZoom {
top: 20px;
right: 10px;
diff --git a/chimere/templates/chimere/category_directory.html b/chimere/templates/chimere/category_directory.html
new file mode 100644
index 0000000..916bd38
--- /dev/null
+++ b/chimere/templates/chimere/category_directory.html
@@ -0,0 +1,35 @@
+{% extends "chimere/base.html" %}
+{% load i18n chimere_tags %}
+{% load url from future %}
+{% block extra_head %}
+ {{ block.super }}
+ {{ form.media }}
+ {% head_jquery %}
+{% endblock %}
+{% block message_map %}{% endblock %}
+{% block message_edit%}{% endblock %}
+{% block content %}
+ {{ block.super }}
+ <div id="category-directory-content">
+ {% if not object_list.count %}
+ <p>{% trans "No category defined!" %}</p>
+ {% else %}
+ <ul id="category-directory" class="list-group">{% for object in object_list %}
+ {% ifchanged object.category %}
+ {% if forloop.counter0 %}
+ </ul>
+ </li>
+ {% endif %}
+ <li class='list-group-item' id='{{object.category|slugify}}'><p class='category-directory-category'>{{object.category}}</p>
+ <ul>
+ {% endifchanged %}
+ <li class='list-group-item'><span class='icon'><img src='{{MEDIA_URL}}{{object.icon.image}}'/></span><a href="{% url 'chimere:category-directory-detail' area_name object.slug %}">{{object.name}} ({{object.item_nb}})</a></li>
+ {% endfor %}
+ </ul>
+ </li>
+ </ul>
+ {% endif %}
+ </div>
+{% endblock %}
+
+
diff --git a/chimere/templates/chimere/category_directory_detail.html b/chimere/templates/chimere/category_directory_detail.html
new file mode 100644
index 0000000..1b23b7e
--- /dev/null
+++ b/chimere/templates/chimere/category_directory_detail.html
@@ -0,0 +1,25 @@
+{% extends "chimere/base.html" %}
+{% load i18n chimere_tags %}
+{% load url from future %}
+{% block extra_head %}
+ {{ block.super }}
+ {{ form.media }}
+ {% head_jquery %}
+{% endblock %}
+{% block message_map %}{% endblock %}
+{% block message_edit%}{% endblock %}
+{% block content %}
+ {{ block.super }}
+ <ol class="breadcrumb">
+ <li><a href="{% url 'chimere:category-directory' area_name %}#{{category.category.name|slugify}}">{{category.category.name}}</a></li>
+ <li class="active">{{category.name}}</li>
+ </ol>
+ <ul id="category-directory" class="list-group">{% for marker in items %}
+ <li class='list-group-item' id='{{item.name|slugify}}'>
+ {% include "chimere/category_item_detail.html" %}
+ </li>
+ {% endfor %}
+ </ul>
+{% endblock %}
+
+
diff --git a/chimere/templates/chimere/category_item_detail.html b/chimere/templates/chimere/category_item_detail.html
new file mode 100644
index 0000000..3f90c6c
--- /dev/null
+++ b/chimere/templates/chimere/category_item_detail.html
@@ -0,0 +1,38 @@
+{% load i18n sanitize chimere_tags %}
+
+<h2>{{ marker.name }}</h2>
+<div class='detail_content'>
+ {% if marker.default_pictures or marker.default_pictures or marker.default_multimedia_items%}
+ <div class='small-gallery'>
+ {% for picture in marker.default_pictures %}
+ {% multimedia_render picture %}
+ {%endfor%}
+ {% for multimedia_item in marker.default_multimedia_items %}
+ {% multimedia_render multimedia_item %}
+ {%endfor%}
+ </div>
+ {%endif%}
+ <div>
+ {% if dated %}
+ <p class='detail_start_date'><label>{% trans "Date:" %}</label> <span>{{marker.start_date|date:"D d M Y"}}
+ {% if marker.end_date %} - {{marker.end_date|date:"D d M Y"}}</p>{% endif %}</span>
+ {% endif %}
+ {% if marker.description %}
+ <p class='description'>{{ marker.description|sanitize:"p b i br hr strong em img:src:alt span:style a:href:target ul li ol h1 h2 h3 h4 table td tr th"|safe}}</p>
+ {% endif %}
+ {% for property in marker.getProperties %}
+ <p class='{{property.propertymodel.getNamedId}}'>{{ property.value|sanitize:"p b i br hr strong em img:src:alt span:style a:href:target ul li ol h1 h2 h3 h4 table td tr th"|safe}}</p>
+ {% endfor %}
+ {% if marker.origin %}<p class='detail_source'><strong>{% trans "Source:" %}</strong> <span>{{marker.origin}}</span></p>{% endif %}
+ {% if marker.license %}<p class='detail_license'><strong>{% trans "License:" %}</strong> <span>{{marker.license}}</span></p>{% endif %}
+ {% share_bar marker.name %}
+ <a href="{% get_tinyfied_url marker area_name %}">{% trans "See on the map" %}</a>
+ <p class='detail_amendment'><a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'>
+ {% trans "Submit an amendment" %}
+ </a>
+ {% if moderator_emails %}
+ <a href="mailto:?from={{moderator_emails}}&subject={% trans "Propose amendment" %}&body={% trans "I would like to propose an amendment for this item:"%} {{share_url}}">
+ {% trans "Propose amendment" %}
+ </a>{%endif%}
+ </div>
+</div>
diff --git a/chimere/urls.py b/chimere/urls.py
index 28a7098..b9ec380 100644
--- a/chimere/urls.py
+++ b/chimere/urls.py
@@ -23,10 +23,11 @@ from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured
admin.autodiscover()
-from chimere.models import Area
+from chimere.views import CategoryDirectoryView, CategoryView
from chimere.feeds import LatestPOIsByCategory, LatestPOIsBySubCategory, \
LatestPOIs, LatestPOIsByZone, LatestPOIsByZoneID
+
def i18n_javascript(request):
return admin.site.i18n_javascript(request)
@@ -121,6 +122,10 @@ urlpatterns += patterns('chimere.views',
'processRouteFile', name='process_route_file'),
url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?dyn/(?P<page_id>\w+)/$',
'extraPage', name='extra_page'),
+ url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/$',
+ CategoryDirectoryView.as_view(), name='category-directory'),
+ url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/(?P<category_slug>[a-zA-Z0-9_-]+)$',
+ CategoryView.as_view(), name='category-directory-detail'),
# At the end, because it catches large
url(r'^(?P<area_name>[a-zA-Z0-9_-]+)?', 'index', name="index"),
)
diff --git a/chimere/views.py b/chimere/views.py
index 0dd5cd5..e6adb3e 100644
--- a/chimere/views.py
+++ b/chimere/views.py
@@ -38,12 +38,13 @@ from django.core import serializers
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.db.models import Q
-from django.http import HttpResponseRedirect, HttpResponse
-from django.shortcuts import redirect, render_to_response
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from django.shortcuts import get_object_or_404, redirect, render_to_response
from django.template import loader, RequestContext, defaultfilters
from django.utils import simplejson as json
from django.utils.http import urlquote
from django.utils.translation import ugettext as _
+from django.views.generic import TemplateView, ListView
from chimere.actions import actions
from chimere.models import Category, SubCategory, PropertyModel, Page,\
@@ -599,6 +600,55 @@ def checkDate(q):
)
return q
+def _getGeoObjects(area_name, category_ids, status='A', getjson=True,
+ item_types=('Marker', 'Route')):
+ '''
+ Get markers and routes
+ '''
+ items = []
+ current_cat, colors, idx = None, None, 0
+ empty = [] if not getjson else {}
+
+ # marker
+ if 'Marker' in item_types:
+ try:
+ q = checkDate(Q(status__in=status, categories__in=category_ids))
+ query = Marker.objects.filter(q).distinct('pk').order_by('-pk')
+ except:
+ return empty
+
+ category_ids = [int(cat_id) for cat_id in category_ids]
+ if getjson:
+ for geo_object in list(query):
+ items += json.loads(geo_object.getGeoJSON(category_ids))
+ else:
+ items += list(query)
+
+ # routes
+ if 'Route' in item_types:
+ query = AggregatedRoute.objects.filter(status__in=status,
+ subcategory__in=category_ids).order_by('subcategory', '-pk')
+ if getjson:
+ for route in query.all():
+ c_cat = route.subcategory
+ if not current_cat or current_cat != c_cat:
+ idx = 0
+ current_cat = c_cat
+ colors = list(Color.objects.filter(
+ color_theme=c_cat.color_theme))
+ if colors:
+ items.append(json.loads(
+ route.getGeoJSON(color=colors[idx % len(colors)].code)))
+ else:
+ items.append(json.loads(route.getGeoJSON(color='000')))
+ idx += 1
+ else:
+ items += list(query)
+
+ if not items:
+ return empty
+ return items
+
def getGeoObjects(request, area_name, category_ids, status):
'''
Get the JSON for markers and routes
@@ -606,31 +656,9 @@ def getGeoObjects(request, area_name, category_ids, status):
if not status:
status = 'A'
status = status.split('_')
- category_ids = category_ids.split('_')
- query = AggregatedRoute.objects.filter(status__in=status,
- subcategory__in=category_ids).order_by('subcategory')
- jsons = []
- current_cat, colors, idx = None, None, 0
- for route in query.all():
- c_cat = route.subcategory
- if not current_cat or current_cat != c_cat:
- idx = 0
- current_cat = c_cat
- colors = list(Color.objects.filter(color_theme = c_cat.color_theme))
- if colors:
- jsons.append(json.loads(
- route.getGeoJSON(color=colors[idx % len(colors)].code)))
- else:
- jsons.append(json.loads(route.getGeoJSON(color='000')))
- idx += 1
- try:
- q = checkDate(Q(status__in=status, categories__in=category_ids))
- query = Marker.objects.filter(q).distinct('pk').order_by('pk')
- except:
- return HttpResponse('no results')
- category_ids = [int(cat_id) for cat_id in category_ids]
- for geo_object in list(query):
- jsons += json.loads(geo_object.getGeoJSON(category_ids))
+ category_ids = unicode(category_ids).split('_')
+
+ jsons = _getGeoObjects(area_name, category_ids, status)
if not jsons:
return HttpResponse('no results')
data = json.dumps({"type": "FeatureCollection", "features":jsons})
@@ -759,6 +787,78 @@ def redirectFromTinyURN(request, area_name='', tiny_urn=''):
return redir
return HttpResponseRedirect(response_dct['extra_url'] + parameters)
+class CategoryDirectoryView(ListView):
+ template_name = "chimere/category_directory.html"
+
+ def get_queryset(self):
+ self.area_name = self.kwargs.get('area_name', None)
+ if self.area_name:
+ self.area_name = self.area_name.split('/')[0]
+ area = get_object_or_404(Area, urn=self.area_name, available=True)
+ q = area.subcategories.filter(available=True,
+ category__available=True
+ ).order_by('category__order', 'category__id', 'order')
+ if q.count():
+ return q
+ return SubCategory.objects.filter(available=True,
+ category__available=True
+ ).order_by('category__order', 'category__id', 'order')
+
+ def get_context_data(self, *args, **kwargs):
+ context = super(CategoryDirectoryView, self).get_context_data(
+ *args, **kwargs)
+ new_context, redirect = get_base_response(self.request, self.area_name)
+ context.update(new_context)
+ context.update({
+ 'actions':actions(self.area_name),
+ 'action_selected':('categories',),
+ })
+ return context
+
+class CategoryView(TemplateView):
+ template_name = "chimere/category_directory_detail.html"
+
+ def get_geo_items(self):
+ # TODO: simplify on v2.3 when slug are available
+ category_slug = self.kwargs.get('category_slug')
+ self.area_name = self.kwargs.get('area_name', None)
+ q = None
+ if self.area_name:
+ self.area_name = self.area_name.split('/')[0]
+ area = get_object_or_404(Area, urn=self.area_name, available=True)
+ q = area.subcategories.filter(available=True,
+ category__available=True)
+ if not q.count():
+ q = None
+ if not q:
+ q = SubCategory.objects.filter(available=True,
+ category__available=True)
+ self.category = None
+ for subcat in q:
+ if defaultfilters.slugify(subcat.name) == category_slug:
+ self.category = subcat
+ break
+ if not self.category:
+ raise Http404(_("Category does not exist"))
+
+ items = _getGeoObjects(self.area_name, [unicode(self.category.pk)],
+ getjson=False, item_types=('Marker',))
+ return items
+
+ def get_context_data(self, *args, **kwargs):
+ context = super(CategoryView, self).get_context_data(
+ *args, **kwargs)
+ self.items = self.get_geo_items()
+ new_context, redirect = get_base_response(self.request, self.area_name)
+ context.update(new_context)
+ context.update({
+ 'actions':actions(self.area_name),
+ 'action_selected':('categories',),
+ 'category':self.category,
+ 'items':self.items
+ })
+ return context
+
def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2,
transport='foot', speed=''):
'''