summaryrefslogtreecommitdiff
path: root/chimere_rss
diff options
context:
space:
mode:
Diffstat (limited to 'chimere_rss')
-rw-r--r--chimere_rss/__init__.py1
-rw-r--r--chimere_rss/feeds.py230
-rw-r--r--chimere_rss/templates/rss.html73
-rw-r--r--chimere_rss/templates/rss_descr.html8
-rw-r--r--chimere_rss/templates/rss_title.html2
-rw-r--r--chimere_rss/urls.py42
-rw-r--r--chimere_rss/views.py140
7 files changed, 496 insertions, 0 deletions
diff --git a/chimere_rss/__init__.py b/chimere_rss/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/chimere_rss/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/chimere_rss/feeds.py b/chimere_rss/feeds.py
new file mode 100644
index 0000000..18a4259
--- /dev/null
+++ b/chimere_rss/feeds.py
@@ -0,0 +1,230 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010 Pierre Clarenc <pierre.crc_AT_gmailDOTcom>,
+# Samuel Renard <renard.samuel_AT_gmailDOTcom>,
+# Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.utils.translation import ugettext as _
+from django.contrib.syndication.feeds import Feed
+from django.contrib.syndication.feeds import FeedDoesNotExist
+from chimere.main.models import Category, SubCategory, Marker, Area
+from django.core.exceptions import ObjectDoesNotExist
+from django.contrib.gis.geos import *
+
+from chimere import settings
+
+class BaseFeed(Feed):
+ """
+ Base feed for Chimere objects
+ """
+ def item_link(self, item):
+ ''' Return POI permalink '''
+ coord = item.point
+ cat = 0
+ if item.categories.all() and item.categories.all()[0]:
+ cat = item.categories.all()[0].pk
+ return settings.BASE_URL + '?zoom=16&lat=%d&lon=%d&current_feature=%d&\
+checked_categories=%d' % (coord.y, coord.x, item.id, cat)
+
+ def item_pubdate(self, item):
+ """
+ Date of the Marker when it has been available
+ """
+ return item.available_date
+
+ def description(self, obj):
+ return ""
+
+class LatestPOIsByCategory(BaseFeed):
+ '''
+ Last Points of interests by category in Feeds
+ '''
+ title_template = "rss_title.html"
+ description_template = "rss_descr.html"
+
+ def get_object(self, bits):
+ """
+ Get extra url, after rss/category/ id of category
+ """
+ if len(bits) != 1:
+ raise ObjectDoesNotExist
+ return Category.objects.get(id__exact=bits[0])
+
+ def title(self, obj):
+ """
+ Define the title of the feed
+ """
+ return u"%s - %s" % (settings.PROJECT_NAME, obj.name)
+
+ def link(self, obj):
+ """
+ Define the link of the feed.
+ """
+ if not obj:
+ raise FeedDoesNotExist
+ return settings.BASE_URL + 'rss/category/' + str(obj.id)
+
+ def items(self, obj):
+ """
+ Requests to marker where its category match the category is requested
+ and its status is available
+ This returns a list of the 15 last markers/POIs ordering by date
+ """
+ q = Marker.objects.filter(status__exact='A',
+ categories__category__id__exact=obj.id,
+ available_date__isnull=False).order_by('-available_date')[:15]
+ return q
+
+class LatestPOIsBySubCategory(BaseFeed):
+ '''
+ Last Points of interests by SubCategory in Feeds
+ '''
+ title_template = "rss_title.html"
+ description_template = "rss_descr.html"
+
+ def get_object(self, bits):
+ if len(bits) != 1:
+ raise ObjectDoesNotExist
+ return SubCategory.objects.get(id__exact=bits[0])
+
+ def title(self, obj):
+ return u"%s - %s - %s" % (settings.PROJECT_NAME, obj.category.name,
+ obj.name)
+
+ def link(self, obj):
+ if not obj:
+ raise FeedDoesNotExist
+ return settings.BASE_URL + 'rss/subcategory/' + str(obj.id)
+
+ def items(self, obj):
+ q = Marker.objects.filter(categories__id__exact=obj.id,
+ available_date__isnull=False, status__exact='A').order_by(
+ '-available_date')[:15]
+ return q
+
+class LatestPOIs(BaseFeed):
+ '''
+ Last Points of interests
+ '''
+ title_template = "rss_title.html"
+ description_template = "rss_descr.html"
+
+ def title(self):
+ return settings.PROJECT_NAME + u" - " + _(u"Last points of interest")
+
+ def link(self):
+ return settings.BASE_URL + 'rss/categories/'
+
+ def description(self):
+ return _("Latest points of interest from ") + settings.PROJECT_NAME
+
+ def items(self):
+ q = Marker.objects.filter(status__exact='A',
+ available_date__isnull=False).order_by('-available_date')[:15]
+ return q
+
+class LatestPOIsByZone(BaseFeed):
+ '''
+ Last Points of interests by zone by coordinates
+ '''
+ title_template = "rss_title.html"
+ description_template = "rss_descr.html"
+ upper_left_lat = 0
+ upper_left_lon = 0
+ lower_right_lat = 0
+ lower_right_lon = 0
+
+ def get_object(self, bits):
+ """
+ Get the extra url. Parameters are the coordinates of the zone (the
+ upper left and lower right points)
+ """
+ if len(bits) != 1:
+ raise ObjectDoesNotExist
+ # Then define the upper right and lower left points
+ coordinates = str(bits[0]).split('_')
+ upper_left_lat = float(coordinates[0])
+ upper_left_lon = float(coordinates[1])
+ lower_right_lat = float(coordinates[2])
+ lower_right_lon = float(coordinates[3])
+ upper_right_lat = upper_left_lat
+ upper_right_lon = lower_right_lon
+ lower_left_lat = lower_right_lat
+ lower_left_lon = upper_left_lon
+ # Define a Polygon with the 4 points of the zone.
+ areaBox = Polygon(((upper_left_lon, upper_left_lat),
+ (upper_right_lon, upper_right_lat),
+ (lower_right_lon, lower_right_lat),
+ (lower_left_lon, lower_left_lat),
+ (upper_left_lon, upper_left_lat)),
+ srid=settings.EPSG_DISPLAY_PROJECTION)
+ return areaBox
+
+ def title(self, obj):
+ return settings.PROJECT_NAME + u" - " +\
+ _(u"Last points of interest by area")
+
+ def link(self, obj):
+ """
+ Define the link of the feed. It's the same url as we get in the method
+ get_object
+ """
+ if not obj:
+ raise FeedDoesNotExist
+ return settings.BASE_URL + 'rss/area/' \
+ + str(self.upper_left_lat) + '_' + str(self.upper_left_lon) + \
+ '_' + str(self.lower_right_lat) + '_' + str(self.lower_right_lon)
+
+ def items(self, obj):
+ """
+ Request to return Markers WHERE there points are containes in the zone
+ which is requested.
+ This returns a list of the 15 last markers/POIs ordering by date
+ """
+ q = Marker.objects.filter(point__contained=obj, status__exact='A',
+ available_date__isnull=False).order_by('-available_date')[:15]
+ return q
+
+class LatestPOIsByZoneID(BaseFeed):
+ '''
+ Last Points of interests by zone by id
+ '''
+ title_template = "rss_title.html"
+ description_template = "rss_descr.html"
+
+ def get_object(self, bits):
+ if len(bits) != 1:
+ raise ObjectDoesNotExist
+ return Area.objects.get(id__exact=bits[0])
+
+ def title(self, obj):
+ return settings.PROJECT_NAME + u" - " + \
+ _(u"Last points of interest") + u" - " + obj.name
+
+ def link(self, obj):
+ if not obj:
+ raise FeedDoesNotExist
+ return settings.BASE_URL + 'rss/areaid/' + str(obj.id)
+
+ def items(self, obj):
+ sql = 'select * from "main_marker" where ' + obj.getIncludeSql()
+ sql += ' and "main_marker".available_date is not null'
+ sql += ' and "main_marker".status=\'A\''
+ sql += ' order by "main_marker".available_date desc limit 15'
+ q = Marker.objects.raw(sql)
+ return q
diff --git a/chimere_rss/templates/rss.html b/chimere_rss/templates/rss.html
new file mode 100644
index 0000000..0c895ed
--- /dev/null
+++ b/chimere_rss/templates/rss.html
@@ -0,0 +1,73 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block sidebar %}
+{% endblock %}
+
+{% block content %}
+<div id='content'>
+<fieldset class='edit'>
+<legend>{% trans "Subscribe to RSS feed" %}</legend>
+
+<p><font color='red'> {{ error_message }} </font></p>
+
+<form method='post' id='rss_form' name='rss_form' action=''>
+{%if not category_rss_feed %}
+<div class="fieldWrapper">
+ <label for="rss_category">{% trans "Type of RSS feed" %}</label>
+ <select name='rss_category' id='rss_category' onchange='document.forms["rss_form"].submit();'>
+ <option value=""> ---- </option>
+ <option value="global">{% trans "All new points of interest" %}</option>
+ <option value="poi">{% trans "New points of interest by category" %}</option>
+ <option value="area">{% trans "New points of interest by area" %}</option>
+ </select>
+</div>
+{% endif %}
+
+{%ifequal category_rss_feed "category" %}
+<h3>{% trans "New points of interest by category" %}</h3>
+<div class="fieldWrapper">
+ <label for="id_subcategory">{% trans "Choose a category" %}</label>
+ <select name='subcategory' id='subcategory' onchange='document.forms["rss_form"].submit();'>
+ {% for cat_subcat in sub_categories %}
+ <option value ="cat_{{cat_subcat.0.id}}"> ---- {{cat_subcat.0.name}} ----
+ {% for sub_category in cat_subcat.1 %}
+ <option value='{{sub_category.id}}'{% ifequal sub_category.id current_category %} selected='selected'{% endifequal %}>
+ {% trans sub_category.name %}
+ </option>{% endfor %}
+ </option>{% endfor %}
+ </select>
+</div>
+{% endifequal %}
+
+{%ifequal category_rss_feed "area" %}
+<h3>{% trans "New points of interest by area" %}</h3>
+{% if area_id %}
+<div class="fieldWrapper">
+ <label for="id_area">{% trans "Choose a pre-defined areas" %}</label>
+ <select name='id_area' id='id_area' onchange='document.forms["rss_form"].submit();'>
+ <option value="" selected="selected"> ---- </option>
+ {% for areaID in area_id %}
+ <option value ={{areaID.id}}>{{areaID.name}}</option>
+ {% endfor %}
+ </select>
+</div>
+
+</form>
+
+<form method='post' action=''>
+{% endif %}
+<div class='fieldWrapper'>
+<label>{% trans "Or select the area by zooming and panning this map" %}</label>
+<div class="map">
+ {{form.area}}
+</div>
+</div>
+<p><input type="submit" value="{% trans "Validate" %}" /></p>
+{% endifequal %}
+
+</form>
+
+</fieldset>
+</div>
+{% endblock %}
diff --git a/chimere_rss/templates/rss_descr.html b/chimere_rss/templates/rss_descr.html
new file mode 100644
index 0000000..4f75ac6
--- /dev/null
+++ b/chimere_rss/templates/rss_descr.html
@@ -0,0 +1,8 @@
+{% load i18n %}
+{% load sanitize %}
+<div id='detail_content'>
+{% if obj.picture %}<img src='{{obj.picture.url}}' alt="{{obj.name}}"/>{%endif%}
+<div>{% for property in obj.getProperties %}
+<p id='{{property.propertymodel.getNamedId}}'>{{ property.value|sanitize:"p b i br hr strong em span:style a:href:target ul li ol h1 h2 h3 h4"|safe }}</p>
+{% endfor %}</div>
+</div>
diff --git a/chimere_rss/templates/rss_title.html b/chimere_rss/templates/rss_title.html
new file mode 100644
index 0000000..5b379e7
--- /dev/null
+++ b/chimere_rss/templates/rss_title.html
@@ -0,0 +1,2 @@
+{% load i18n %}
+{{ obj.name }}
diff --git a/chimere_rss/urls.py b/chimere_rss/urls.py
new file mode 100644
index 0000000..e5e9a24
--- /dev/null
+++ b/chimere_rss/urls.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010 Pierre Clarenc <pierre.crc_AT_gmailDOTcom>,
+# Samuel Renard <renard.samuel_AT_gmailDOTcom>,
+# Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+
+from django.conf.urls.defaults import *
+
+from chimere.rss.feeds import LatestPOIsByCategory, LatestPOIsBySubCategory, \
+ LatestPOIs, LatestPOIsByZone, LatestPOIsByZoneID
+from chimere.urls import EXTRA_NO_AREA as EXTRA
+
+feeds = {
+ 'category': LatestPOIsByCategory,
+ 'subcategory': LatestPOIsBySubCategory,
+ 'global': LatestPOIs,
+ 'area': LatestPOIsByZone,
+ 'areaid': LatestPOIsByZoneID
+}
+
+urlpatterns = patterns('',
+ (EXTRA + r'rss/$', 'chimere.rss.views.rss'),
+ (EXTRA + r'rss/(?P<url>.*)/$',
+ 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
+)
+
diff --git a/chimere_rss/views.py b/chimere_rss/views.py
new file mode 100644
index 0000000..1d6381d
--- /dev/null
+++ b/chimere_rss/views.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010 Pierre Clarenc <pierre.crc_AT_gmailDOTcom>,
+# Samuel Renard <renard.samuel_AT_gmailDOTcom>,
+# Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+"""
+Views of the project
+"""
+
+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+from django.utils.translation import ugettext as _
+
+from chimere import settings
+from chimere.main.views import get_base_response
+from chimere.main.actions import actions
+from chimere.main.models import SubCategory,Area
+from chimere.main.forms import AreaForm
+from chimere.main.widgets import AreaWidget
+
+def rss(request, area_name=''):
+ '''
+ Redirect to RSS subscription page
+ '''
+ response_dct = get_base_response()
+ response_dct.update({'actions':actions, 'action_selected':('rss',),
+ 'category_rss_feed':'',})
+ # If the form has been submited
+ if request.method == "POST":
+ # User has defined the kind of POI he is interested in : POI in a area
+ # (GET method is used for the link with RSS icon in the browser)
+ if 'rss_category' in request.POST:
+ #User wants to follow all the new POI
+ if request.POST['rss_category'] == 'global':
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/global/'
+ return HttpResponseRedirect(feeds_link)
+ # User wants to follow all the new POI by category or subcategory
+ elif request.POST['rss_category'] == 'poi':
+ response_dct['category_rss_feed'] = 'category'
+ response_dct['sub_categories'] = SubCategory.getAvailable()
+ return render_to_response('rss.html', response_dct)
+ # User wants to follow all the new POI situated in a defined area
+ elif request.POST['rss_category'] == 'area':
+ # An unbound form
+ form = AreaForm()
+ area_widget = AreaWidget().render('area', None)
+ response_dct.update({'map_layer':settings.MAP_LAYER,
+ 'extra_head':form.media,
+ 'form':form,
+ 'category_rss_feed':'area',
+ 'area_id':Area.getAvailable(),
+ 'area_widget':area_widget
+ })
+ return render_to_response('rss.html', response_dct)
+ # Error when submitting the form
+ else:
+ error = _("Incorrect choice in the list")
+ response_dct.update({'error_message':error,
+ 'category_rss_feed':'',
+ 'sub_categories':SubCategory.getAvailable()})
+ return render_to_response('rss.html', response_dct)
+
+ # User has specified the category or subcategory he wants to follow =>
+ # we redirect him towards the related rss feed
+ if 'subcategory' in request.POST and request.POST['subcategory'] != '':
+ idCat = request.POST['subcategory']
+ if idCat.find("cat_") != -1 :
+ list_Cat = idCat.split('_')
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/category/'
+ feeds_link += list_Cat[1]
+ return HttpResponseRedirect(feeds_link)
+
+ else:
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/subcategory/' + \
+ idCat
+ return HttpResponseRedirect(feeds_link)
+
+ # User has specified the ID of the area he wants to follow
+ if 'id_area' in request.POST and request.POST['id_area'] != '':
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/areaid/' \
+ + request.POST['id_area']
+ return HttpResponseRedirect(feeds_link)
+
+ # User has specified the area he wants to follow => we redirect him
+ # towards the related rss feed (using upper left and lower right
+ # coordinates)
+ elif 'upper_left_lat' in request.POST and \
+ request.POST['upper_left_lat'] != '' and \
+ 'upper_left_lon' in request.POST and \
+ request.POST['upper_left_lon'] != '' and \
+ 'lower_right_lon' in request.POST and \
+ request.POST['lower_right_lon'] != '' and \
+ 'lower_right_lat' in request.POST and \
+ request.POST['lower_right_lat'] != '' :
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/area/' + \
+request.POST['upper_left_lat'] + '_' + request.POST['upper_left_lon'] + '_' + \
+request.POST['lower_right_lat'] + '_' + request.POST['lower_right_lon']
+ return HttpResponseRedirect(feeds_link)
+
+
+ # GET method is used for linking with the RSS icon in the browser when user
+ # wants to choose a category to follow
+ elif request.method == "GET" and 'rss_category' in request.GET:
+ if request.GET['rss_category'] == 'global':
+ feeds_link = '/' + settings.EXTRA_URL + 'rss/global/'
+ return HttpResponseRedirect(feeds_link)
+ if request.GET['rss_category'] == 'poi':
+ response_dct['category_rss_feed'] = 'category'
+ response_dct['sub_categories'] = SubCategory.getAvailable(['M','B'])
+ return render_to_response('rss.html', response_dct)
+ if request.GET['rss_category'] == 'area':
+ # An unbound form
+ form = AreaForm()
+ response_dct.update({'map_layer':settings.MAP_LAYER,
+ 'extra_head':form.media,
+ 'form':form,
+ 'category_rss_feed':'area',
+ 'area_id':Area.getAvailable(),
+ 'area_widget':AreaWidget().render('area', None)})
+ return render_to_response('rss.html', response_dct)
+
+ # User access to the RSS tab
+ else:
+ return render_to_response('rss.html', response_dct)