renkan state management for staff members : publish, unpublish, reject.
--- a/src/hdalab/models/renkan.py Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/models/renkan.py Fri Sep 05 12:43:52 2014 +0200
@@ -4,23 +4,31 @@
@author: tc
'''
from django.db import models
+from django.utils.translation import ugettext as _
from renkanmanager.models import Renkan
class HdalabRenkan(models.Model):
EDITION = 1
- PUBLISHED = 2
- MODERATED = 3
+ MODERATED = 2
+ PUBLISHED = 3
REJECTED = 4
STATE_CHOICES = (
(EDITION, 'edition'),
+ (MODERATED, 'moderated'),
(PUBLISHED, 'published'),
- (MODERATED, 'moderated'),
(REJECTED, 'rejected'),
)
+ STATE_CHOICES_DICT = {
+ EDITION: _('edition_state'),
+ MODERATED: _('moderated_state'),
+ PUBLISHED: _('published_state'),
+ REJECTED: _('rejected_state')
+ }
+
renkan = models.ForeignKey(Renkan, blank=False, null=False)
state = models.IntegerField(choices=STATE_CHOICES, default=1)
--- a/src/hdalab/templates/base.html Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/templates/base.html Fri Sep 05 12:43:52 2014 +0200
@@ -30,7 +30,7 @@
<li><a class="{% block categories_actif %}{% endblock %}" href="{% url 'categories' %}">Catégories de Wikipedia</a></li>
<li><a class="{% block thesaurus_actif %}{% endblock %}" href="{% url 'thesaurus' %}">Thésaurus</a></li>
<li>—</li>
- <li><a class="{% block renkans_actif %}{% endblock %}" href="{% url 'renkan_public_list' %}">Renkans</a></li>
+ <li><a class="{% block renkans_actif %}{% endblock %}" href="{% url 'renkan_public_list' %}">Renkans</a>{% if user.is_staff %} <a href="{% url 'edito_home' %}">({% trans 'Manage' %})</a>{% endif %}</li>
<li>—</li>
{% if user.is_authenticated %}
<li><a class="{% block profile_actif %}{% endblock %}" href="{% url 'profile_home' %}">{{ user.username }}</a></li>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/editorial/edito_home.html Fri Sep 05 12:43:52 2014 +0200
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load static %}
+{% load hdabo_tags %}
+{% block title %}HdaLab - Éditorialisation : Tous les dossiers{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+<link rel="stylesheet" type="text/css" href="{% static 'hdalab/css/profile.css' %}" />
+{% endblock %}
+
+{% block main_content %}
+<p><a href="{% url 'manage_renkans' %}">Management des Renkans : acceptation ou rejet des publications</a></p>
+<p><a href="{% url 'hdalab_folders' %}">Dossiers d'éditorialisation</a></p>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/editorial/manage_renkans.html Fri Sep 05 12:43:52 2014 +0200
@@ -0,0 +1,52 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% load static %}
+{% load thumbnail %}
+{% load hdalab_tags %}
+
+{% block title %}{{block.super}} > {% trans 'Manage renkan publication' %}{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+ <link rel="stylesheet" type="text/css" href="{% static 'hdalab/css/index.css' %}" />
+ <link rel="stylesheet" type="text/css" href="{% static 'hdalab/css/ui-lightness/jquery-ui-1.10.4.min.css' %}" />
+ <link rel="stylesheet" type="text/css" href="{% static 'hdalab/css/profile.css' %}" />
+{% endblock %}
+
+{% block js_import %}
+{{block.super}}
+ <script src="{% static 'hdalab/js/profile.js' %}"></script>
+ <script src="{% static 'hdalab/lib/jquery.tablesorter.min.js' %}"></script>
+ <script type="text/javascript">
+ $(document).ready(function(){
+ $("#rk-table").tablesorter({headers: { 3: { sorter: false }, 5: { sorter: false } }});
+ });
+ </script>
+{% endblock %}
+
+{% block main_content %}
+ <table id="rk-table">
+ <thead>
+ <tr class="border_bottom"><th>Nom</th><th>Utilisateur</th><th>Date de modification</th><th>Preview</th><th>Statut</th><th>Actions</th></tr>
+ </thead>
+ <tbody>
+ {% for hr in renkan_list %}
+ {% with hr.renkan as r %}
+ <tr class="border_bottom">
+ <td>{{ r.title }}</td>
+ <td>{{ r.owner.username }}</td>
+ <td>{{ r.modification_date|date:"Y-m-d H:i" }}</td>
+ <td>{% thumbnail r.image 100x100 as thumb %}<img src="{{ thumb.url }}" width="{{ thumb.width }}" height="{{ thumb.height }}" /></td>
+ <td>{{ hr.state|state_to_str }}</td>
+ <td>
+ <a title="View renkan" href="{% url 'renkan_view' %}?rk_id={{ r.rk_id }}" class="renkan-basic-action"><span class="ui-icon ui-icon-eye"></span></a>
+ {% if hr.state == 2 or hr.state == 4 %}<a title="Publish renkan" href="{% url 'renkan_moderate' rk_id=r.rk_id state=3 %}?next={% url 'manage_renkans' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to PUBLISH this renkan ?" %}');" ><span class="ui-icon ui-icon-unlocked"></span></a>
+ {% else %}<a title="Unpublish renkan" href="{% url 'renkan_moderate' rk_id=r.rk_id state=1 %}?next={% url 'manage_renkans' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to UNPUBLISH this renkan ?" %}');" ><span class="ui-icon ui-icon-locked"></span></a>{% endif %}
+ {% if hr.state != 4 %}<a title="Reject renkan" href="{% url 'renkan_moderate' rk_id=r.rk_id state=4 %}?next={% url 'manage_renkans' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to REJECT this renkan ?" %}');" ><span class="ui-icon ui-icon-close"></span></a>{% endif %}
+ </td>
+ </tr>
+ {% endwith %}
+ {% endfor %}
+ </tbody>
+ </table>
+{% endblock %}
\ No newline at end of file
--- a/src/hdalab/templates/profile_home.html Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/templates/profile_home.html Fri Sep 05 12:43:52 2014 +0200
@@ -2,6 +2,7 @@
{% load i18n %}
{% load static %}
{% load thumbnail %}
+{% load hdalab_tags %}
{% block title %}{{block.super}} > Profil utilisateur : {{ user.username }}{% endblock %}
@@ -39,15 +40,17 @@
{% for hr in renkan_list %}
{% with hr.renkan as r %}
<tr class="border_bottom">
- <td>{{ r.title }} ({{ r.id }})</td>
+ <td>{{ r.title }}</td>
<td>{{ r.modification_date|date:"Y-m-d H:i" }}</td>
<td>{% thumbnail r.image 100x100 as thumb %}<img src="{{ thumb.url }}" width="{{ thumb.width }}" height="{{ thumb.height }}" /></td>
- <td>{{ hr.state }}</td>
+ <td>{{ hr.state|state_to_str }}</td>
<td>
<a title="Edit renkan" href="{% url 'renkan_edit' %}?rk_id={{ r.rk_id }}" class="renkan-basic-action"><span class="ui-icon ui-icon-pencil"></span></a>
<a title="View renkan" href="{% url 'renkan_view' %}?rk_id={{ r.rk_id }}" class="renkan-basic-action"><span class="ui-icon ui-icon-eye"></span></a>
<a title="Copy renkan" href="{% url 'renkan_copy' rk_id=r.rk_id %}?next={% url 'profile_home' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to copy this renkan ?" %}');" ><span class="ui-icon ui-icon-copy"></span></a>
<a title="Remove renkan" href="{% url 'renkan_delete' rk_id=r.rk_id %}?next={% url 'profile_home' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to delete this renkan ? You cannot undo this action." %}');" ><span class="ui-icon ui-icon-trash"></span></a>
+ {% if hr.state == 1 %}<a title="Publish renkan" href="{% url 'renkan_moderate' rk_id=r.rk_id state=2 %}?next={% url 'profile_home' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to ask to publish this renkan ?" %}');" ><span class="ui-icon ui-icon-unlocked"></span></a>
+ {% else %}<a title="Unpublish renkan" href="{% url 'renkan_moderate' rk_id=r.rk_id state=1 %}?next={% url 'profile_home' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to unpublish this renkan ?" %}');" ><span class="ui-icon ui-icon-locked"></span></a>{% endif %}
</td>
</tr>
{% endwith %}
--- a/src/hdalab/templates/renkan_list.html Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/templates/renkan_list.html Fri Sep 05 12:43:52 2014 +0200
@@ -30,7 +30,7 @@
<h2>Liste des renkans publiques</h2>
<table id="rk-table">
<thead>
- <tr class="border_bottom"><th>Nom</th><th>Date de modification</th><th>Preview</th><th>Statut</th><th>Actions</th></tr>
+ <tr class="border_bottom"><th>Nom</th><th>Date de modification</th><th>Preview</th><th>Actions</th></tr>
</thead>
<tbody>
{% for hr in renkan_list %}
@@ -39,7 +39,6 @@
<td>{{ r.title }} ({{ r.id }})</td>
<td>{{ r.modification_date|date:"Y-m-d H:i" }}</td>
<td>{% thumbnail r.image 100x100 as thumb %}<img src="{{ thumb.url }}" width="{{ thumb.width }}" height="{{ thumb.height }}" /></td>
- <td>{{ hr.state }}</td>
<td>
<a title="View renkan" href="{% url 'renkan_view' %}?rk_id={{ r.rk_id }}" class="renkan-basic-action"><span class="ui-icon ui-icon-eye"></span></a>
<a title="Copy renkan" href="{% url 'renkan_copy' rk_id=r.rk_id %}?next={% url 'profile_home' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to copy this renkan ?" %}');" ><span class="ui-icon ui-icon-copy"></span></a>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templatetags/hdalab_tags.py Fri Sep 05 12:43:52 2014 +0200
@@ -0,0 +1,18 @@
+from django.template import Library, TemplateSyntaxError
+from hdalab.models.renkan import HdalabRenkan
+
+register = Library()
+
+import logging
+logger = logging.getLogger(__name__)
+
+@register.filter
+def state_to_str(value):
+ """ """
+ # Error management
+ if value is None or not isinstance(value, int) :
+ raise TemplateSyntaxError('status_to_str value error : int is required')
+ return HdalabRenkan.STATE_CHOICES_DICT.get(value, "")
+state_to_str.is_safe = True
+
+
--- a/src/hdalab/urls.py Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/urls.py Fri Sep 05 12:43:52 2014 +0200
@@ -2,10 +2,12 @@
from django.conf.urls import patterns, include, url
from django.views.generic import TemplateView
from hdalab.views.profile import ProfileHome, RenkanEdit, HdalabRenkanGetPut,\
- RenkanNew, RenkanPublicList, HdalabRenkanCopy, HdalabRenkanDelete
+ RenkanNew, RenkanPublicList, HdalabRenkanCopy, HdalabRenkanDelete,\
+ HdalabRenkanModerate
from django.contrib.auth.decorators import login_required
+from django.contrib.admin.views.decorators import staff_member_required
from hdalab.views.editorial import HdalabFolders, HdalabAddOrUpdateFolder,\
- HdalabDeleteFolder
+ HdalabDeleteFolder, ManageRenkans
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
@@ -40,14 +42,17 @@
url(r'^renkan/view/$', TemplateView.as_view(template_name="renkan_view.html"), name='renkan_view'),
url(r'^renkan/copy/(?P<rk_id>.*)$', login_required(HdalabRenkanCopy.as_view()), name='renkan_copy'),
url(r'^renkan/delete/(?P<rk_id>.*)$', login_required(HdalabRenkanDelete.as_view()), name='renkan_delete'),
+ url(r'^renkan/moderate/(?P<rk_id>.*)/(?P<state>.*)$', login_required(HdalabRenkanModerate.as_view()), name='renkan_moderate'),
url(r'^profile/$', login_required(ProfileHome.as_view()), name='profile_home'),
url(r'^renkan/public/$', RenkanPublicList.as_view(), name='renkan_public_list'),
url(r'^ajaxlogin/$', "hdalab.views.profile.ajax_login", name='ajax_login'),
url(r'^ajaxloginok/$', TemplateView.as_view(template_name="ajax_identification/ajax_login_ok.html"), name='ajax_login_ok'),
- url(r'^edito/folders/$', login_required(HdalabFolders.as_view()), name='hdalab_folders'),
- url(r'^edito/folder/$', login_required(HdalabAddOrUpdateFolder.as_view()), name='hdalab_add_or_update_folder'),
- url(r'^edito/folder/(?P<folder_pk>[\w-]+)$', login_required(HdalabAddOrUpdateFolder.as_view()), name='hdalab_add_or_update_folder'),
- url(r'^edito/deletefolder/(?P<folder_pk>[\w-]+)$', login_required(HdalabDeleteFolder.as_view()), name='hdalab_delete_folder'),
+ url(r'^edito/$', staff_member_required(TemplateView.as_view(template_name="editorial/edito_home.html")), name='edito_home'),
+ url(r'^edito/manage/$', staff_member_required(ManageRenkans.as_view()), name='manage_renkans'),
+ url(r'^edito/folders/$', staff_member_required(HdalabFolders.as_view()), name='hdalab_folders'),
+ url(r'^edito/folder/$', staff_member_required(HdalabAddOrUpdateFolder.as_view()), name='hdalab_add_or_update_folder'),
+ url(r'^edito/folder/(?P<folder_pk>[\w-]+)$', staff_member_required(HdalabAddOrUpdateFolder.as_view()), name='hdalab_add_or_update_folder'),
+ url(r'^edito/deletefolder/(?P<folder_pk>[\w-]+)$', staff_member_required(HdalabDeleteFolder.as_view()), name='hdalab_delete_folder'),
)
--- a/src/hdalab/views/editorial.py Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/views/editorial.py Fri Sep 05 12:43:52 2014 +0200
@@ -5,19 +5,25 @@
@author: tc
'''
-#from datetime import datetime
-from django.conf import settings
-from django.shortcuts import get_object_or_404, redirect
-#from django.views.generic import TemplateView, View
-from hdabo.models import Folder
-from hdabo.views import Folders, AddOrUpdateFolder, SearchDatasheet,\
- DeleteFolder
-
+from django.views.generic import TemplateView
+from hdalab.models.renkan import HdalabRenkan
+from hdabo.views import Folders, AddOrUpdateFolder, DeleteFolder
import logging
logger = logging.getLogger(__name__)
+class ManageRenkans(TemplateView):
+ template_name = "editorial/manage_renkans.html"
+
+ def get_context_data(self, **kwargs):
+ context = super(ManageRenkans, self).get_context_data(**kwargs)
+
+ context["renkan_list"] = HdalabRenkan.objects.exclude(state=HdalabRenkan.EDITION).select_related("renkan", "renkan__owner").order_by("-renkan__modification_date")
+
+ return context
+
+
class HdalabFolders(Folders):
template_name = "editorial/folders.html"
--- a/src/hdalab/views/profile.py Wed Sep 03 17:22:23 2014 +0200
+++ b/src/hdalab/views/profile.py Fri Sep 05 12:43:52 2014 +0200
@@ -36,6 +36,7 @@
import logging
+from django.http.response import Http404
logger = logging.getLogger(__name__)
@@ -73,10 +74,8 @@
rk.save()
hr = HdalabRenkan()
hr.renkan = rk
- from random import randrange
- hr.state = randrange(4) + 1
+ hr.state = HdalabRenkan.EDITION
hr.save()
-
return redirect("%s?rk_id=%s" % (reverse('renkan_edit'), rk_id))
@@ -474,6 +473,26 @@
+class HdalabRenkanModerate(View):
+
+ def get(self, request, rk_id, state):
+ if rk_id!="":
+ try:
+ hr = HdalabRenkan.objects.select_related("renkan", "renkan__owner").get(renkan__rk_id=rk_id)
+ except:
+ raise Http404('Renkan not found')
+ if hr.renkan.owner!=request.user and not request.user.is_staff:
+ return HttpResponseBadRequest("You are not allowed to modify the state this renkan.")
+ hr.state = state
+ hr.save()
+
+ if "next" in request.GET:
+ return redirect(request.GET["next"])
+
+ return redirect(reverse('profile_home'))
+
+
+
# Function copied from django.contrib.auth.views to simplify ajax login
@sensitive_post_parameters()
@csrf_protect