Commit 8ba2f1f2 authored by Claude Paroz's avatar Claude Paroz

Add support for more than one coordinator per team

parent 3a881756
......@@ -39,18 +39,15 @@ class TeamManager(models.Manager):
roles.
"""
teams = self.all()
roles = Role.objects.select_related("person").filter(role='coordinator',
is_active=True)
roles = Role.objects.select_related("person").filter(role='coordinator')
role_dict = {}
for role in roles:
# Only one coordinator by team
role_dict[role.team_id] = role
role_dict.setdefault(role.team_id, []).append(role.person)
for team in teams:
try:
role = role_dict[team.id]
team.roles = {'coordinator': [role.person]}
team.roles = {'coordinator': role_dict[team.id]}
except KeyError:
# Abnormal because a team must have a coordinator but of no
# consequence
......@@ -102,7 +99,7 @@ class Team(models.Model):
def __init__(self, *args, **kwargs):
models.Model.__init__(self, *args, **kwargs)
self.roles = None
self.roles = {}
def __unicode__(self):
return self.description
......@@ -115,8 +112,8 @@ class Team(models.Model):
""" Return True if user is allowed to edit this team
user is a User (from request.user), not a Person
"""
coordinator = self.get_coordinator()
return user.is_authenticated() and coordinator and user.username == coordinator.username
return (user.is_authenticated() and
user.username in [p.username for p in self.get_coordinators()])
def fill_role(self, role, person):
""" Used by TeamManager to prefill roles in team """
......@@ -133,27 +130,18 @@ class Team(models.Model):
def get_languages(self):
return self.language_set.all()
def get_coordinator(self):
try:
return self.roles['coordinator'][0]
except:
try:
# The join by role__team__id generates only one query and
# the same one by role__team=self two queries!
return Person.objects.get(role__team__id=self.id,
role__role='coordinator')
except Person.DoesNotExist:
return None
def get_members_by_role_exact(self, role):
def get_members_by_role_exact(self, role, only_active=True):
""" Return a list of active members """
try:
return self.roles[role]
except:
members = list(Person.objects.filter(role__team__id=self.id,
role__role=role,
role__is_active=True))
return members
except KeyError:
members = Person.objects.filter(role__team__id=self.id, role__role=role)
if only_active:
members = members.filter(role__is_active=True)
return list(members)
def get_coordinators(self):
return self.get_members_by_role_exact('coordinator', only_active=False)
def get_committers_exact(self):
return self.get_members_by_role_exact('committer')
......@@ -164,17 +152,17 @@ class Team(models.Model):
def get_translators_exact(self):
return self.get_members_by_role_exact('translator')
def get_members_by_roles(self, roles):
def get_members_by_roles(self, roles, only_active=True):
"""Requires a list of roles in argument"""
try:
members = []
for role in roles:
members += self.roles[role]
except:
members = list(Person.objects.filter(role__team__id=self.id,
role__role__in=roles,
role__is_active=True))
return members
except KeyError:
members = Person.objects.filter(role__team__id=self.id, role__role__in=roles)
if only_active:
members = members.filter(role__is_active=True)
return list(members)
def get_committers(self):
return self.get_members_by_roles(['coordinator', 'committer'])
......@@ -188,7 +176,7 @@ class Team(models.Model):
members = []
for role in ['coordinator', 'committer', 'reviewer', 'translator']:
members += self.roles[role]
except:
except KeyError:
# Not necessary to filter as for other roles
members = list(self.members.all())
return members
......@@ -202,8 +190,8 @@ class Team(models.Model):
def send_mail_to_coordinator(self, subject, message, messagekw={}):
""" Send a message to the coordinator, in her language if available
and if subject and message are lazy strings """
coordinator = self.get_coordinator()
if not coordinator or not coordinator.email:
recipients = [pers.email for pers in self.get_coordinators() if pers.email]
if not recipients:
return
prev_lang = translation.get_language()
translation.activate(self.language_set.all()[0].locale)
......@@ -214,7 +202,7 @@ class Team(models.Model):
subject,
message,
settings.DEFAULT_FROM_EMAIL,
[coordinator.email]
recipients
)
translation.activate(prev_lang)
......@@ -242,8 +230,8 @@ class FakeTeam(object):
def get_languages(self):
return (self.language,)
def get_coordinator(self):
return None
def get_coordinators(self):
return []
ROLE_CHOICES = (
......
......@@ -18,47 +18,33 @@ class TeamsAndRolesTests(TestCase):
self.pn.set_password('password')
self.pn.save()
self.pt = Person(first_name='John', last_name='Translator',
self.pt = Person.objects.create(first_name='John', last_name='Translator',
email='jt@tf1.com', username= 'jt')
self.pt.save()
self.pr = Person(first_name='John', last_name='Reviewer',
self.pr = Person.objects.create(first_name='John', last_name='Reviewer',
email='jr@csa.com', username= 'jr')
self.pr.save()
self.pc = Person(first_name='John', last_name='Committer',
self.pc = Person.objects.create(first_name='John', last_name='Committer',
email='jc@alinsudesonpleingre.fr', username= 'jc',
last_login=datetime.now()-timedelta(days=30*6-1)) #active person, but in limit date
self.pc.save()
self.pcoo = Person(first_name='John', last_name='Coordinator',
email='jcoo@imthebigboss.fr', username= 'jcoo')
self.pcoo.set_password('password')
self.pcoo.save()
self.t = Team(name='fr', description='French', mailing_list='french_ml@example.org')
self.t.save()
self.t2 = Team(name='pt', description='Portuguese')
self.t2.save()
self.l = Language(name='French', locale='fr', team=self.t)
self.l.save()
self.role = Role(team=self.t, person=self.pt)
self.role.save()
self.role = Role(team=self.t2, person=self.pt, role='reviewer')
self.role.save()
self.t = Team.objects.create(name='fr', description='French',
mailing_list='french_ml@example.org')
self.role = Role(team=self.t, person=self.pr, role='reviewer')
self.role.save()
self.t2 = Team.objects.create(name='pt', description='Portuguese')
self.role = Role(team=self.t, person=self.pc, role='committer')
self.role.save()
self.l = Language.objects.create(name='French', locale='fr', team=self.t)
self.role = Role(team=self.t, person=self.pcoo, role='coordinator')
self.role.save()
_ = Role.objects.create(team=self.t, person=self.pt)
_ = Role.objects.create(team=self.t2, person=self.pt, role='reviewer')
_ = Role.objects.create(team=self.t, person=self.pr, role='reviewer')
_ = Role.objects.create(team=self.t, person=self.pc, role='committer')
_ = Role.objects.create(team=self.t, person=self.pcoo, role='coordinator')
class TeamTest(TeamsAndRolesTests):
def setUp(self):
......@@ -91,8 +77,8 @@ class TeamTest(TeamsAndRolesTests):
self.assertEqual(members[0], self.pc)
def run_roles_exact_test(self, team):
pcoo = team.get_coordinator()
self.assertEqual(pcoo, self.pcoo)
pcoords = team.get_coordinators()
self.assertEqual(pcoords[0], self.pcoo)
members = team.get_committers_exact()
self.assert_(len(members), 1)
......
......@@ -46,7 +46,6 @@ def teams(request, format='html'):
def team(request, team_slug):
try:
team = Team.objects.get(name=team_slug)
coordinator = team.get_coordinator()
mem_groups = (
{'title': _("Committers"),
'members': team.get_committers_exact(),
......@@ -72,7 +71,6 @@ def team(request, team_slug):
except Team.DoesNotExist:
lang = get_object_or_404(Language, locale=team_slug)
team = FakeTeam(lang)
coordinator = None
mem_groups = ()
context = {
......
......@@ -45,14 +45,12 @@
<div class="bloc half">
<h2>{% trans "Coordinator" %}</h2>
{% if team.get_coordinator %}
{% with team.get_coordinator as person %}
{% for person in team.get_coordinators %}
{% include "people/person_overview.html" %}
{% endwith %}
{% else %}
{% empty %}
<p><em>{% trans "This team has currently no coordinator." %}<br>
{% blocktrans with link="http://live.gnome.org/TranslationProject/TeamCoordinatorResponsibilities" %}See <a href="{{ link }}">the GTP Wiki</a> for more information about coordinatorship.{% endblocktrans %}</em></p>
{% endif %}
{% endfor %}
</div>
</div>
......
{% extends "base.html" %}
{% load i18n %}
{% load i18n people %}
{% block title %}{% trans "GNOME Translation Teams" %}{% endblock %}
......@@ -22,14 +22,12 @@
<a href="{{ team.get_absolute_url }}">{{ team.translated_name }}</a>
&mdash;
<span style="font-size: 80%;">
{% with team.get_coordinator as coordinator %}
{% if coordinator %}
{% blocktrans with coordinator.get_absolute_url|safe as url and coordinator.name as name %}Coordinated by <a href="{{ url }}">{{ name }}</a>{% endblocktrans %}
{% if team.get_coordinators %}
{% blocktrans with plist=team.get_coordinators|people_list %}Coordinated by {{ plist }}</a>{% endblocktrans %}
{% else %}
<em>{% trans "No coordinator" %}</em>
{% endif %}
</span>
{% endwith %}
</li>
{% endfor %}
</ul>
......
<teams>
{% for team in teams %}
<team id="{{ team.name }}">
{% with team.get_coordinator as coordinator %}
<description>{{ team.description }}</description>
{% if coordinator and coordinator.svn_account %}
{% for coordinator in team.get_coordinators %}
<coordinator>
<name>{{ coordinator.name }}</name>
<vcs>{{ coordinator.svn_account }}</vcs>
{% if coordinator.svn_account %}<vcs>{{ coordinator.svn_account }}</vcs>{% endif %}
</coordinator>
{% endif %}
{% endwith %}
{% endfor %}
</team>
{% endfor %}
</teams>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment