changeset 344:32d0e87d3fd5

News: display group news list, display a single news item (w/o comments)
author Sylvain Beucler <beuc@beuc.net>
date Sun, 29 Aug 2010 11:04:25 +0200
parents c1d7767e3abf
children a812fdfce278
files savane/svmain/views.py savane/svnews/urls.py savane/svnews/views.py savane/urls.py settings_default.py templates/svmain/homepage.html templates/svnews/news_detail.html templates/svnews/news_list.html templates/svnews/news_list.inc templates/svnews/news_list_short.inc templates/svnews/user_submitted_by_link.inc
diffstat 11 files changed, 222 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/savane/svmain/views.py
+++ b/savane/svmain/views.py
@@ -89,6 +89,7 @@
 
     import savane.svnews.models as svnews_models
     news_list = svnews_models.News.objects.filter(is_approved=1).order_by('-date')[:9]
+    news_count = svnews_models.News.objects.filter(is_approved=1).count()
 
     # nb_users and nb_groups as string, because the |add: template
     # filter only accepts strings.
@@ -99,6 +100,7 @@
         'group_confs' : group_confs,
         'category_list' : category_list,
         'news_list' : news_list,
+        'news_count' : news_count,
         }
     return context
 
new file mode 100644
--- /dev/null
+++ b/savane/svnews/urls.py
@@ -0,0 +1,52 @@
+# News URLs
+# Copyright (C) 2010  Sylvain Beucler
+#
+# This file is part of Savane.
+# 
+# Savane is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# Savane 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 Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.conf import settings
+from django.conf.urls.defaults import *
+from django.utils.translation import ugettext, ugettext_lazy as _
+from django.views.generic.list_detail import object_detail, object_list
+from django.views.generic.create_update import create_object, update_object
+from django.contrib.auth.decorators import login_required
+import models as svnews_models
+import views
+#import forms as svnews_forms
+from savane.perms import only_project_admin
+from savane.django_utils import decorated_patterns
+
+urlpatterns = patterns ('',)
+
+urlpatterns += patterns ('',
+  url(r'^$', views.redirect_to_admin_group,
+      {},
+      name='news_list_admin_group'),
+  url(r'^(?P<object_id>\d+)/$', object_detail,
+      { 'queryset' : svnews_models.News.objects.filter(is_approved__in=(0,1,2,)) },
+      name='news_detail'),
+  url(r'^(?P<slug>[-\w]+)/$', views.news_list_by_group,
+      { 'queryset' : svnews_models.News.objects.filter(is_approved__in=(0,1,2,)).order_by('-date') },
+      name='news_list_by_group'),
+)
+urlpatterns += decorated_patterns ('', only_project_admin,
+  url(r'^(?P<slug>[-\w]+)/manage/$', object_list,
+      { 'extra_context' : { 'title' : _("Manage"), }, },
+      name='news_manage_by_group'),
+  url(r'^(?P<slug>[-\w]+)/(?P<object_id>\d+)/edit/$', update_object,
+      { 'model' : svnews_models.News,
+        'extra_context' : { 'title' : _("Manage"), }, },
+      name='news_edit'),
+)
new file mode 100644
--- /dev/null
+++ b/savane/svnews/views.py
@@ -0,0 +1,37 @@
+# News
+# Copyright (C) 2010  Sylvain Beucler
+#
+# This file is part of Savane.
+#
+# Savane is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# Savane 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.conf import settings
+from django.shortcuts import get_object_or_404
+from django.views.generic.simple import redirect_to
+from django.views.generic.list_detail import object_list
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _, ungettext
+import django.contrib.auth.models as auth_models
+
+def redirect_to_admin_group(*args, **kwargs):
+    group = get_object_or_404(auth_models.Group, name=settings.SV_ADMIN_GROUP)
+    kwargs['url']=reverse('savane:svnews:news_list_by_group', args=[group.name])
+    return redirect_to(*args, **kwargs)
+
+def news_list_by_group(request, slug, *args, **kwargs):
+    group = get_object_or_404(auth_models.Group, name=slug)
+    kwargs['queryset'] = kwargs['queryset'].filter(group=group)
+    kwargs['extra_context'] = kwargs.get('extra_context', {})
+    kwargs['extra_context']['group'] = group
+    return object_list(request, *args, **kwargs)
--- a/savane/urls.py
+++ b/savane/urls.py
@@ -8,6 +8,7 @@
   (r'', include('savane.svmain.urls', namespace='svmain')),
   # User account
   (r'^my/', include('savane.my.urls', namespace='my')),
+  (r'^news/', include('savane.svnews.urls', namespace='svnews')),
   (r'^people/', include('savane.svpeople.urls', namespace='svpeople')),
   (r'^tracker/', include('savane.tracker.urls', namespace='tracker')),
 )
--- a/settings_default.py
+++ b/settings_default.py
@@ -153,3 +153,7 @@
 
 # django-registration
 ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window
+
+
+# Savane-specific
+SV_ADMIN_GROUP = 'siteadmin'
--- a/templates/svmain/homepage.html
+++ b/templates/svmain/homepage.html
@@ -62,23 +62,15 @@
   <!-- /intro -->
   </div>
 
-  <div class="boxtitle"><a href="TODO">{% trans "Latest news" %}</a></div>
-  {% for object in news_list %}
-  <div class="{% cycle 'boxitem' 'boxitemalt' %}">
-    <a href="TODO"><strong>{{object.summary}}</strong></a><br />
-    &nbsp;&nbsp;&nbsp;&nbsp;
-    <span class="smaller"><em>
-      {% trans "posted by" %}
-      <a href="{% url savane:svmain:user_detail object.submitted_by.username %}"
-      >{{object.submitted_by.username}}</a>,
-      {{object.date}} -
-      {% blocktrans count object.comment_set.count as count %}{{count}} comment{% plural %}{{count}} comments{% endblocktrans %}
-    </em></span>
-    <br />
-    {{object.details|svmarkup_full}}
-    TODO: conditional [Read more]
+  <div class="boxtitle"><a href="{% url savane:svnews:news_list_admin_group %}">{% trans "Latest news" %}</a></div>
+  {% with news_list as object_list %}
+  {% include 'svnews/news_list.inc' %}
+  {% endwith %}
+  <div class="smaller {% cycle rowcolor %}">
+    <a href="{% url savane:svnews:news_list_admin_group %}"
+      >[{% blocktrans count news_count as count %}{{count}} news in archive{% plural %}{{count}} news in archive{% endblocktrans %}]
+    </a>
   </div>
-  {% endfor %}
 </div>
 
 {% endblock %}
new file mode 100644
--- /dev/null
+++ b/templates/svnews/news_detail.html
@@ -0,0 +1,31 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% load svmarkup %}
+
+{% block title %}
+{% trans "News" %}{% trans ": " %}{{object.summary}}
+{% endblock %}
+
+{% block icon %}news{% endblock %}
+
+{% block content %}
+
+<h2><a href="">{{object.summary}}</a></h2>
+
+<p><em>
+  {% trans "Posted by" %}
+  {% include 'svnews/user_submitted_by_link.inc' %}
+  {{object.date}}
+</em></p>
+
+{{object.details|svmarkup_full}}
+
+{% endblock %}
+
+{% comment %}
+Local Variables: **
+mode: django-html **
+tab-width: 4 **
+indent-tabs-mode: nil **
+End: **
+{% endcomment %}
new file mode 100644
--- /dev/null
+++ b/templates/svnews/news_list.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %}
+{{group.svgroupinfo.get_full_name_display}}{% trans ": " %}{{title}}
+{% endblock %}
+
+{% block icon %}news{% endblock %}
+
+{% block content %}
+
+<div class="box">
+  <div class="boxtitle">{% trans "Latest approved news - with summaries" %}</div>
+  {% with object_list|slice:":10" as object_list %}
+  {% if object_list %}
+  {% include 'svnews/news_list.inc' %}
+  {% else %}
+  <h2>{% trans "No news items found" %}</h2>
+  {% endif %}
+  {% endwith %}
+</div>
+
+<br />
+
+{% if object_list.count > 10 %}
+<div class="box">
+  <div class="boxtitle">{% trans "Older approved news" %}</div>
+  {% with object_list|slice:"10:" as object_list %}
+  {% include 'svnews/news_list_short.inc' %}
+  {% endwith %}
+</div>
+{% endif %}
+
+{% endblock %}
+
+{% comment %}
+Local Variables: **
+mode: django-html **
+tab-width: 4 **
+indent-tabs-mode: nil **
+End: **
+{% endcomment %}
new file mode 100644
--- /dev/null
+++ b/templates/svnews/news_list.inc
@@ -0,0 +1,18 @@
+{% load i18n %}
+{% load svmarkup %}
+
+{% for object in object_list %}
+<div class="{% cycle 'boxitem' 'boxitemalt' as rowcolor %}">
+  <a href="{% url savane:svnews:news_detail object.pk %}"><strong>{{object.summary}}</strong></a><br />
+  &nbsp;&nbsp;&nbsp;&nbsp;
+  <span class="smaller"><em>
+    {% trans "posted by" %}
+    {% include 'svnews/user_submitted_by_link.inc' %}
+    {{object.date}} -
+    {% blocktrans count object.comment_set.count as count %}{{count}} comment{% plural %}{{count}} comments{% endblocktrans %}
+  </em></span>
+  <br />
+  {{object.details|svmarkup_full}}
+  TODO: conditional [Read more]
+</div>
+{% endfor %}
new file mode 100644
--- /dev/null
+++ b/templates/svnews/news_list_short.inc
@@ -0,0 +1,14 @@
+{% load i18n %}
+{% load svmarkup %}
+
+{% for object in object_list %}
+<div class="{% cycle 'boxitem' 'boxitemalt' as rowcolor %}">
+  <a href="{% url savane:svnews:news_detail object.pk %}"><strong>{{object.summary}}</strong></a>
+  <span class="smaller"><em>
+    {% trans "posted by" %}
+    {% include 'svnews/user_submitted_by_link.inc' %}
+    {{object.date}} -
+    {% blocktrans count object.comment_set.count as count %}{{count}} comment{% plural %}{{count}} comments{% endblocktrans %}
+  </em></span>
+</div>
+{% endfor %}
new file mode 100644
--- /dev/null
+++ b/templates/svnews/user_submitted_by_link.inc
@@ -0,0 +1,13 @@
+{% load i18n %}
+
+{% if object.submitted_by_id %}
+  {% if object.submitted_by %}
+  <a href="{% url savane:svmain:user_detail object.submitted_by.username %}"
+  >{{object.submitted_by.get_full_name}}
+&lt;{{object.submitted_by.username}}&gt;</a>,
+  {% else %}
+    <strong>{% trans "Invalid user ID" %}</strong>,
+  {% endif %}
+{% else %}
+{% trans "Anonymous" %},
+{% endif %}