Skip to content

Commit

Permalink
Merge "(no-ticket) Add team list view"
Browse files Browse the repository at this point in the history
  • Loading branch information
pawloKoder authored and Gerrit Code Review committed Jun 16, 2014
2 parents d786331 + 2f79307 commit a1901a4
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 5 deletions.
87 changes: 87 additions & 0 deletions oioioi/teams/fixtures/test_team.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
[
{
"pk": 1103,
"model": "auth.user",
"fields": {
"username": "test_team1",
"first_name": "Test",
"last_name": "Team1",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2012-07-31T20:27:58.768Z",
"groups": [],
"user_permissions": [],
"password": "",
"email": "[email protected]",
"date_joined": "2012-07-31T20:27:58.768Z"
}
},
{
"pk": 1104,
"model": "auth.user",
"fields": {
"username": "test_team2",
"first_name": "Test",
"last_name": "Team2",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2012-07-31T20:27:58.768Z",
"groups": [],
"user_permissions": [],
"password": "",
"email": "[email protected]",
"date_joined": "2012-07-31T20:27:58.768Z"
}
},
{
"pk": 1105,
"model": "auth.user",
"fields": {
"username": "test_team_user",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2012-07-31T20:27:58.768Z",
"groups": [],
"user_permissions": [],
"password": "",
"email": "",
"date_joined": "2012-07-31T20:27:58.768Z"
}
},
{
"pk": 1,
"model": "teams.team",
"fields": {
"name": "test_team",
"login": "test_team_user",
"user": [
"test_team_user"
],
"contest": "c",
"join_key": "abrakadabra"
}
},
{
"pk": 1,
"model": "teams.teamMembership",
"fields": {
"user": 1103,
"team": 1105
}
},
{
"pk": 2,
"model": "teams.teamMembership",
"fields": {
"user": [
"test_team2"
],
"team": 1105
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding field 'TeamsConfig.teams_list_visible'
db.add_column(u'teams_teamsconfig', 'teams_list_visible',
self.gf('oioioi.base.fields.EnumField')(default='NO', max_length=64),
keep_default=False)


def backwards(self, orm):
# Deleting field 'TeamsConfig.teams_list_visible'
db.delete_column(u'teams_teamsconfig', 'teams_list_visible')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'contests.contest': {
'Meta': {'object_name': 'Contest'},
'controller_name': ('oioioi.base.fields.DottedNameField', [], {'max_length': '255', 'superclass': "'oioioi.contests.controllers.ContestController'"}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'default_submissions_limit': ('django.db.models.fields.IntegerField', [], {'default': '10', 'blank': 'True'}),
'id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
u'teams.team': {
'Meta': {'object_name': 'Team'},
'contest': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contests.Contest']"}),
'join_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'login': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
},
u'teams.teammembership': {
'Meta': {'unique_together': "(('user', 'team'),)", 'object_name': 'TeamMembership'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'members'", 'to': u"orm['teams.Team']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'teams.teamsconfig': {
'Meta': {'object_name': 'TeamsConfig'},
'contest': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['contests.Contest']", 'unique': 'True'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'max_team_size': ('django.db.models.fields.IntegerField', [], {'default': '3'}),
'modify_begin_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'modify_end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'teams_list_visible': ('oioioi.base.fields.EnumField', [], {'default': "'NO'", 'max_length': '64'})
}
}

complete_apps = ['teams']
9 changes: 9 additions & 0 deletions oioioi/teams/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.utils.translation import ugettext_lazy as _
from django.core.validators import MinValueValidator
from django.core.exceptions import ValidationError
from oioioi.base.fields import EnumRegistry, EnumField

from oioioi.contests.models import Contest

Expand Down Expand Up @@ -53,6 +54,12 @@ def validate_unique(self, *args, **kwargs):
{'user': {"The user is already in another team"}})


teams_list_visibility_options = EnumRegistry()
teams_list_visibility_options.register('PUBLIC', _("Visible for all"))
teams_list_visibility_options.register('YES', _("Visible only for registered users"))
teams_list_visibility_options.register('NO', _("Not visible"))


class TeamsConfig(models.Model):
contest = models.OneToOneField(Contest)
enabled = models.BooleanField(default=False)
Expand All @@ -62,6 +69,8 @@ class TeamsConfig(models.Model):
verbose_name=_("team modification begin date"), blank=True, null=True)
modify_end_date = models.DateTimeField(
verbose_name=_("team modification end date"), blank=True, null=True)
teams_list_visible = EnumField(teams_list_visibility_options, default='NO',
verbose_name=_("teams list visibility"))

class Meta(object):
verbose_name = _("teams configuration")
Expand Down
21 changes: 21 additions & 0 deletions oioioi/teams/templates/teams/teams.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% extends "base-with-menu.html" %}
{% load i18n %}
{% load pagination_tags %}

{% block title %}{% trans "Teams" %}{% endblock %}

{% block content %}

<h2>{{ name }}</h2>
<ul>
{% for team in teams %}
<li>{{ team.name }}</li>
<ul>
{% for member in team.members %}
<li>{{ member }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>

{% endblock %}
67 changes: 66 additions & 1 deletion oioioi/teams/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from oioioi.teams.utils import can_join_team, can_quit_team, can_delete_team, \
can_create_team
from oioioi.teams.views import create_team
from oioioi.teams.models import TeamMembership
from oioioi.teams.models import TeamMembership, Team


class TestTeamsViews(TestCase, SubmitFileMixin):
Expand Down Expand Up @@ -154,3 +154,68 @@ def test_submit_file_with_team_deleted(self):
tm.delete()
self.client.post(url, post_data)
self.assertEqual(Submission.objects.get().user, user)


class TestTeamsListView(TestCase):
fixtures = ['test_users', 'test_contest', 'test_team']

def test_visibility_no(self):
contest = Contest.objects.get()
tconf = TeamsConfig(contest=contest,
enabled=True, teams_list_visible='NO')
tconf.save()

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertNotIn('Teams', response.content)

self.client.login(username='test_user')

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertNotIn('Teams', response.content)

def test_visibility_yes(self):
contest = Contest.objects.get()
tconf = TeamsConfig(contest=contest,
enabled=True, teams_list_visible='YES')
tconf.save()

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertNotIn('Teams', response.content)

self.client.login(username='test_user')

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertIn('Teams', response.content)

def test_visibility_public(self):
contest = Contest.objects.get()
tconf = TeamsConfig(contest=contest,
enabled=True, teams_list_visible='PUBLIC')
tconf.save()

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertIn('Teams', response.content)

self.client.login(username='test_user')

response = self.client.get(reverse('default_contest_view',
kwargs={'contest_id': contest.id}), follow=True)
self.assertIn('Teams', response.content)

def test_list(self):
contest = Contest.objects.get()
tconf = TeamsConfig(contest=contest,
enabled=True, teams_list_visible='PUBLIC')
tconf.save()

response = self.client.get(reverse('teams_list',
kwargs={'contest_id': contest.id}), follow=True)

self.assertIn('<li>test_team</li>', response.content)
self.assertIn('<li>Test Team1</li>', response.content)
self.assertIn('<li>Test Team2</li>', response.content)
1 change: 1 addition & 0 deletions oioioi/teams/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

contest_patterns = patterns('oioioi.teams.views',
url(r'^team/$', 'team_view', name='team_view'),
url(r'^teams/$', 'teams_list', name='teams_list'),
url(r'^team/join/(?P<join_key>[0-9a-f]+)$', 'join_team_view',
name='join_team'),
url(r'^team/delete/$', 'delete_team_view', name='delete_team'),
Expand Down
18 changes: 16 additions & 2 deletions oioioi/teams/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from oioioi.base.permissions import make_request_condition
from oioioi.teams.models import TeamMembership, TeamsConfig
from oioioi.base.permissions import make_request_condition, not_anonymous
from oioioi.contests.utils import is_contest_admin
from oioioi.teams.models import Team, TeamMembership, TeamsConfig


@make_request_condition
Expand All @@ -10,6 +11,19 @@ def teams_enabled(request):
return False


@make_request_condition
def can_see_teams_list(request):
if not Team.objects.filter(contest=request.contest).exists():
return False
try:
cfg = TeamsConfig.objects.get(contest=request.contest)
except TeamsConfig.DoesNotExist:
return is_contest_admin(request)
return is_contest_admin(request) | \
(cfg.teams_list_visible == 'PUBLIC') | \
((cfg.teams_list_visible == 'YES') & not_anonymous(request))


def team_members_count(request):
"""Returns a number of members in the team for the user and the contest
from the request.
Expand Down
16 changes: 14 additions & 2 deletions oioioi/teams/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from oioioi.teams.models import Team, TeamMembership
from oioioi.teams.forms import CreateTeamForm
from oioioi.teams.utils import can_create_team, can_join_team, can_quit_team, \
can_delete_team, has_team, teams_enabled
can_delete_team, has_team, teams_enabled, \
can_see_teams_list


def create_team(login, name, contest):
Expand All @@ -25,7 +26,18 @@ def team_members_names(request, team):
for membership in team.members.all()]


@menu_registry.register_decorator(_("Team"), lambda request:
@menu_registry.register_decorator(_("Teams"), lambda request:
reverse('teams_list', kwargs={'contest_id': request.contest.id}),
order=50)
@enforce_condition(can_see_teams_list & contest_exists & can_enter_contest)
def teams_list(request, contest_id):
teams = [{'name': team.name,
'members': team_members_names(request, team)}
for team in Team.objects.filter(contest=request.contest)]
return TemplateResponse(request, 'teams/teams.html', {'teams': teams})


@menu_registry.register_decorator(_("My Team"), lambda request:
reverse('team_view', kwargs={'contest_id': request.contest.id}),
order=50)
@enforce_condition(not_anonymous & contest_exists & can_enter_contest &
Expand Down

0 comments on commit a1901a4

Please sign in to comment.