diff options
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 |
commit | 5953bfdb54bd36f716d7b36681aae2648e3c1028 (patch) | |
tree | ae14b6fc6184b32030e1ab5ede8eceae0e00317f | |
parent | 908744a6f3d5ac40a48f0a52c5167e131785b2cc (diff) | |
download | Chimère-5953bfdb54bd36f716d7b36681aae2648e3c1028.tar.bz2 Chimère-5953bfdb54bd36f716d7b36681aae2648e3c1028.zip |
Add a directory with all available markers
-rw-r--r-- | chimere/actions.py | 13 | ||||
-rw-r--r-- | chimere/models.py | 9 | ||||
-rw-r--r-- | chimere/settings.sample.py | 2 | ||||
-rw-r--r-- | chimere/static/chimere/css/styles.css | 14 | ||||
-rw-r--r-- | chimere/templates/chimere/category_directory.html | 35 | ||||
-rw-r--r-- | chimere/templates/chimere/category_directory_detail.html | 25 | ||||
-rw-r--r-- | chimere/templates/chimere/category_item_detail.html | 38 | ||||
-rw-r--r-- | chimere/urls.py | 7 | ||||
-rw-r--r-- | chimere/views.py | 154 |
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=''): ''' |