damned-lies r1192 - in trunk: . media/img people stats stats/templatetags templates



Author: claudep
Date: Thu Nov 27 19:45:54 2008
New Revision: 1192
URL: http://svn.gnome.org/viewvc/damned-lies?rev=1192&view=rev

Log:
2008-11-27  Claude Paroz  <claude 2xlibre net>

	* media/img/edit.png: Icon for editing.
	* people/urls.py: Add the possibility to display people by username.
	* stats/models.py: New method can_edit_branches for checking permissions.
	Add pre_save check for Branch to verify existence prior to creation.
	* stats/templatetags/stats_extras.py: Custom template filter to join text
	with url, suitable for translatable string without url.
	* templates/module_edit_branches.html:
	* stats/forms.py: 
	* stats/views.py: Template, form and view to edit module branches.
	* templates/base.html: Use new template filter to show connected username
	with link.
	* templates/module.html: Add icon for editing branches. Correct if test.
	* urls.py: URL for new view, and for people username.

Added:
   trunk/media/img/edit.png   (contents, props changed)
   trunk/stats/forms.py
   trunk/stats/templatetags/
   trunk/stats/templatetags/__init__.py
   trunk/stats/templatetags/stats_extras.py
   trunk/templates/module_edit_branches.html
Modified:
   trunk/ChangeLog
   trunk/people/urls.py
   trunk/stats/models.py
   trunk/stats/views.py
   trunk/templates/base.html
   trunk/templates/module.html
   trunk/urls.py

Added: trunk/media/img/edit.png
==============================================================================
Binary file. No diff available.

Modified: trunk/people/urls.py
==============================================================================
--- trunk/people/urls.py	(original)
+++ trunk/people/urls.py	Thu Nov 27 19:45:54 2008
@@ -3,6 +3,7 @@
 
 info_dict = {
     'queryset': Person.objects.all(),
+    'slug_field': 'username',
     'template_object_name': 'person',
     'extra_context': { 
         'pageSection': "teams"
@@ -11,5 +12,7 @@
 
 urlpatterns = patterns('django.views.generic.list_detail',
     url(r'^$', 'object_list', dict(info_dict), 'persons'),                    
-    url(r'(?P<object_id>\d+)/$', 'object_detail', dict(info_dict), 'person')
+    url(r'(?P<object_id>\d+)/$', 'object_detail', dict(info_dict), 'person'),
+    # equivalent to the previous, but using username instead of user pk
+    url(r'(?P<slug>\w+)/$', 'object_detail', dict(info_dict), 'person'),
 )

Added: trunk/stats/forms.py
==============================================================================
--- (empty file)
+++ trunk/stats/forms.py	Thu Nov 27 19:45:54 2008
@@ -0,0 +1,32 @@
+from django import forms
+from stats.models import Module, Branch, Category, CATEGORY_CHOICES, Release
+
+
+class ReleaseField(forms.ModelChoiceField):
+    def __init__(self, *args, **kwargs):
+        super(ReleaseField, self).__init__(*args, **kwargs)
+        if kwargs.has_key('initial'):
+            self.is_branch = True
+
+class ModuleBranchForm(forms.Form):
+    def __init__(self, module, *args, **kwargs):
+        super(ModuleBranchForm, self).__init__(*args, **kwargs)
+        self.branch_fields = []
+        for branch in module.branch_set.all():
+            for cat in branch.category_set.order_by('name', 'release__name'):
+                self.fields[str(cat.id)] = ReleaseField(queryset=Release.objects.all(),
+                                                        label=branch.name,
+                                                        initial=cat.release.pk)
+                self.fields[str(cat.id)+'_cat'] = forms.ChoiceField(choices=CATEGORY_CHOICES,
+                                                                    initial=cat.name)
+                self.fields[str(cat.id)+'_del'] = forms.BooleanField(required=False)
+                self.branch_fields.append((str(cat.id), str(cat.id)+'_cat', str(cat.id)+'_del'))
+                
+        self.fields['new_branch'] = forms.CharField(required=False)
+        self.fields['new_branch_release'] = ReleaseField(queryset=Release.objects.all(), required=False)
+        self.fields['new_branch_category'] = forms.ChoiceField(choices=CATEGORY_CHOICES)
+
+    def get_branches(self):
+        for rel_field, cat_field, del_field in self.branch_fields:
+            yield (self[rel_field], self[cat_field], self[del_field])
+

Modified: trunk/stats/models.py
==============================================================================
--- trunk/stats/models.py	(original)
+++ trunk/stats/models.py	Thu Nov 27 19:45:54 2008
@@ -102,11 +102,25 @@
             if branch.name in ('HEAD', 'trunk', 'master'):
                 return branch
         return None
+    
+    def can_edit_branches(self, user):
+        """ Returns True for superusers, users with adequate permissions or maintainers of the module """ 
+        if user.is_superuser or \
+           user.has_perms(['stats.delete_branch', 'stats.add_branch', 'stats.change_branch']) or \
+           user.username in [p.username for p in self.maintainers.all()]:
+            return True
+        return False
 
+class BranchCharField(models.CharField):
+    def pre_save(self, model_instance, add):
+        """ Check if branch is valid before saving the instance """
+        if not model_instance.checkout():
+            raise Exception, "Branch not valid: error while checking out the branch."
+        return getattr(model_instance, self.attname)
 
 class Branch(models.Model):
     """ Branch of a module """
-    name = models.CharField(max_length=50)
+    name = BranchCharField(max_length=50)
     #description = models.TextField(null=True)
     vcs_subpath = models.CharField(max_length=50, null=True, blank=True)
     module = models.ForeignKey(Module)
@@ -116,6 +130,7 @@
         db_table = 'branch'
         verbose_name_plural = 'branches'
         ordering = ('name',)
+        unique_together = ("name", "module")
 
     def __unicode__(self):
         return "%s (%s)" % (self.name, self.module)
@@ -218,7 +233,7 @@
             
             # 2. Pre-check, if available (intltool-update -m)
             # **************************
-            if dom.dtype == 'ui'and not dom.pot_method:
+            if dom.dtype == 'ui' and not dom.pot_method:
                 # Run intltool-update -m to check for some errors
                 errors.extend(utils.check_potfiles(domain_path))
             
@@ -785,6 +800,7 @@
     class Meta:
         db_table = 'category'
         verbose_name_plural = 'categories'
+        unique_together = ("release", "branch")
 
     def __unicode__(self):
         return "%s (%s, %s)" % (self.get_name_display(), self.release, self.branch)

Added: trunk/stats/templatetags/__init__.py
==============================================================================

Added: trunk/stats/templatetags/stats_extras.py
==============================================================================
--- (empty file)
+++ trunk/stats/templatetags/stats_extras.py	Thu Nov 27 19:45:54 2008
@@ -0,0 +1,10 @@
+from django import template
+
+register = template.Library()
+
+def linked_with(value, arg):
+    """ This filter returns an object (passed in value) enclosed with his absolute url 
+        arg is the linked text """
+    return "<a href='%s'>%s</a>" % (value.get_absolute_url(), arg)
+
+register.filter(linked_with)

Modified: trunk/stats/views.py
==============================================================================
--- trunk/stats/views.py	(original)
+++ trunk/stats/views.py	Thu Nov 27 19:45:54 2008
@@ -19,14 +19,17 @@
 # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 from django.shortcuts import render_to_response, get_object_or_404
-from stats.models import Statistics, Module, Release
-from stats.conf import settings
-from stats import utils
+from django.contrib.auth.decorators import login_required
 from django.core import serializers
 from django.http import HttpResponse
 from django.template import RequestContext
 from django.utils.translation import ugettext_lazy as _
 
+from stats.models import Statistics, Module, Branch, Category, Release
+from stats.forms import ModuleBranchForm
+from stats.conf import settings
+from stats import utils
+
 MIME_TYPES = {'json': 'application/json',
               'xml':  'text/xml'
              }
@@ -43,10 +46,76 @@
     context = {
         'pageSection':  "module",
         'module': mod,
+        'can_edit_branches': mod.can_edit_branches(request.user),
         'prof': utils.Profiler()
     }
     return render_to_response('module.html', context, context_instance=RequestContext(request))
 
+ login_required
+def module_edit_branches(request, module_name):
+    mod = get_object_or_404(Module, name=module_name)
+    messages = []
+    if not mod.can_edit_branches(request.user):
+        request.user.message_set.create(message="Sorry, you're not allowed to edit this module's branches")
+        return module(request, module_name)
+    if request.method == 'POST':
+        form = ModuleBranchForm(mod, request.POST)
+        if form.is_valid():
+            updated = False
+            # Modified or deleted release or category for branch
+            for key, field in form.fields.items():
+                if not getattr(field, 'is_branch', False):
+                    continue
+                if form.cleaned_data[key+'_del']:
+                    # Delete category
+                    Category.objects.get(pk=key).delete()
+                    updated = True
+                    continue
+                release_has_changed = field.initial != form.cleaned_data[key].pk
+                category_has_changed = form.fields[key+'_cat'].initial != form.cleaned_data[key+'_cat']
+                if release_has_changed or category_has_changed:
+                    old_release = Release.objects.get(pk=field.initial)
+                    cat = Category.objects.get(pk=key)
+                    if release_has_changed:
+                        new_release = form.cleaned_data[key]
+                        cat.release = new_release
+                    cat.name = form.cleaned_data[key+'_cat']
+                    cat.save()
+                    updated = True
+            # New branch (or new category)
+            if form.cleaned_data['new_branch']:
+                branch_name = form.cleaned_data['new_branch']
+                try:
+                    branch = Branch.objects.get(module=mod, name=branch_name)
+                except Branch.DoesNotExist:
+                    # It is probably a new branch
+                    try:
+                        branch = Branch(module=mod, name=branch_name)
+                        branch.save()
+                        messages.append("The new branch %s has been added" % branch_name)
+                        updated = True
+                        # Send message to gnome-i18n?
+                    except Exception, e:
+                        messages.append("Error adding the branch '%s': %s" % (branch_name, str(e)))
+                        branch = None
+                if branch and form.cleaned_data['new_branch_release']:
+                    rel = Release.objects.get(pk=form.cleaned_data['new_branch_release'].pk)
+                    cat = Category(release=rel, branch=branch, name=form.cleaned_data['new_branch_category'])
+                    cat.save()
+                    updated = True
+            if updated:
+                form = ModuleBranchForm(mod) # Redisplay a clean form
+        else:
+            messages.append("Sorry, form is not valid")
+    else:  
+        form = ModuleBranchForm(mod)
+    context = {
+        'module': mod,
+        'form': form,
+        'messages': messages
+    }
+    return render_to_response('module_edit_branches.html', context, context_instance=RequestContext(request))
+
 def docimages(request, module_name, potbase, branch_name, langcode):
     mod = get_object_or_404(Module, name=module_name)
     stat = get_object_or_404(Statistics,

Modified: trunk/templates/base.html
==============================================================================
--- trunk/templates/base.html	(original)
+++ trunk/templates/base.html	Thu Nov 27 19:45:54 2008
@@ -1,4 +1,5 @@
 {% load i18n %}
+{% load stats_extras %}
 {% get_current_language as LANGUAGE_CODE %}
 <!DOCTYPE html
      PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
@@ -81,9 +82,9 @@
 <!-- end site header -->
   <div id="authenticated">
   {% if user.is_authenticated %}
-  {% blocktrans with user.username as username %} Logged in as: {{ username }}{% endblocktrans %}
+    {% blocktrans with user|linked_with:user.username|safe as username %}Logged in as: {{ username }}{% endblocktrans %}
   {% else %}
-  <!-- Not useful right now <a href="{% url login %}">{% trans "Login" %}</a> -->
+  <!-- Not useful right now <a href="{% url login %}">{% trans "Log in" %}</a> -->
   {% endif %}
   </div>
 

Modified: trunk/templates/module.html
==============================================================================
--- trunk/templates/module.html	(original)
+++ trunk/templates/module.html	Thu Nov 27 19:45:54 2008
@@ -54,6 +54,9 @@
     {% endifnotequal %}
     <a href="#{{ branch.name }}">{{ branch.name }}</a>
   {% endfor %}
+  {% if can_edit_branches %}
+    <a href="{% url stats.views.module_edit_branches module_name=module.name %}"><img src="/media/img/edit.png" alt="Edit" /></a>
+  {% endif %}
   </p>
 
   <!-- Main loop through branches -->
@@ -73,9 +76,9 @@
     <table><tr><td valign="top"><!-- split to two columns -->
     {% with branch.get_doc_stats as stats %}
     {% if stats|length %}
-      {% ifnotequal stats|length 1 %}
+      {% if not stats|length_is:"1" %}
         <h3>{% trans "Documentation" %}</h3>
-      {% endifnotequal %}
+      {% endif %}
       {% include "stats_show.html" %}
     {% endif %}
     {% endwith %}
@@ -83,9 +86,9 @@
     </td><td valign="top"><!-- split to two columns -->
     {% with branch.get_ui_stats as stats %}
     {% if stats|length %}
-      {% ifnotequal stats|length 1 %}
+      {% if not stats|length_is:"1" %}
         <h3>{% trans "Translation" %}</h3>
-      {% endifnotequal %}
+      {% endif %}
       {% include "stats_show.html" %}
     {% endif %}
     {% endwith %}

Added: trunk/templates/module_edit_branches.html
==============================================================================
--- (empty file)
+++ trunk/templates/module_edit_branches.html	Thu Nov 27 19:45:54 2008
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %} Module Edition (branches) {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1><a href="{% url stats.views.module module_name=module.name %}">{{ module.get_description }}</a></h1>
+
+{% if module.homepage %}
+  <p><a href="{{ module.homepage }}">{{ module.homepage }}</a></p>
+{% endif %}
+
+<form action="#" method="POST">
+<table>
+<tr><th>Branch</th><th>Release</th><th>Category</th></tr>
+{% for field1, field2, field3 in form.get_branches %}
+  <tr><td>{{ field1.label }}</td><td>{{ field1 }}</td><td>{{ field2 }}</td><td>{{ field3 }} <i>delete?</i></td></tr>
+{% endfor %}
+
+  <tr><td>{{ form.new_branch }}</td><td>{{ form.new_branch_release }}</td><td>{{ form.new_branch_category }}</td></tr>
+  <tr><td colspan="3" align="right"><input type="submit" value="Save" /></td></tr> 
+</table>
+</form>
+
+</div>
+{% endblock %}

Modified: trunk/urls.py
==============================================================================
--- trunk/urls.py	(original)
+++ trunk/urls.py	Thu Nov 27 19:45:54 2008
@@ -10,6 +10,8 @@
     url(r'^login/$', 'common.views.site_login', name='login'),
     (r'^teams/', include('teams.urls')),
     (r'^people/', include('people.urls')),
+    # users is the hardcoded url in the contrib.auth User class, making it identical to /people
+    (r'^users/', include('people.urls')),
     (r'^languages/', include('languages.urls')),
     #(r'^stats/', include('stats.urls')),
     (r'^admin/(.*)', admin.site.root),
@@ -18,6 +20,7 @@
 urlpatterns += patterns('stats.views',
     url(r'^module/$', 'modules', name='modules'),
     (r'^module/(?P<module_name>[\w\-\+]+)/$', 'module'),
+    (r'^module/(?P<module_name>[\w\-\+]+)/edit/branches/$', 'module_edit_branches'),
     (r'^module/(?P<module_name>[\w\-\+]+)/(?P<potbase>[\w-]+)/(?P<branch_name>[\w-]+)/(?P<langcode>[\w ]+)/images/$', 'docimages'),
     url(r'^releases/(?P<format>(html|json|xml))?/?$', 'releases', name='releases'),
     (r'^releases/(?P<release_name>[\w-]+)$', 'release'),



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]