Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user to contest form doesn't have an option for direct add #307

Merged
12 changes: 10 additions & 2 deletions oioioi/teachers/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from django.utils.translation import gettext_lazy as _

from oioioi.contests.forms import SimpleContestForm
from oioioi.teachers.models import Teacher
from oioioi.teachers.models import ContestTeacher, Teacher
from oioioi.base.utils.user_selection import UserSelectionField

from oioioi.participants.models import Participant
from django.contrib import messages


class TeacherContestForm(SimpleContestForm):
Expand Down Expand Up @@ -83,3 +84,10 @@ def __init__(self, *args, **kwargs):
def clean_school(self):
data = self.cleaned_data['school']
return ' '.join(data.splitlines())


class AddUserToContestForm(forms.Form):
user = UserSelectionField()

def __init__(self, *args, **kwargs):
super(AddUserToContestForm, self).__init__(*args, **kwargs)
19 changes: 19 additions & 0 deletions oioioi/teachers/templates/teachers/members.html
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,25 @@ <h2 class="method-title" id="members-view">
</p>
{% endif %}

<form action="{% url 'teachers_add_user_to_contest' contest_id=contest.id member_type=member_type %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ ctx.request.get_full_path }}">

<div class="input-group mb-3">
<div class="input-group-prepend">
<button class="btn btn-success" type="submit">
{% if member_type == 'teacher' %}
{% trans "Add a teacher" %}
{% else %}
{% trans "Add a pupil" %}
{% endif %}
</button>
</div>
<input type="text" name="user" id="new-user" class="form-control" placeholder="{% trans "Username" %}" data-hints-url="{% url 'teachers_get_appendable_users' contest_id=contest.id member_type=member_type %}">
<script>init_user_selection("new-user", {{ num_hints }})</script>
</div>
</form>

{% if member_type == 'pupil' and usergroups_active and members %}
<div class="text-center">
<form class="convert-members" action="{% url 'teacher_usergroups_add_group' %}" method="get">
Expand Down
39 changes: 38 additions & 1 deletion oioioi/teachers/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from oioioi.contests.tests.utils import make_user_contest_admin
from oioioi.teachers.models import Teacher

from oioioi.teachers.utils import add_user_to_contest_as as autc, \
UserAddResult as add_res


def change_contest_type(contest):
contest.controller_name = 'oioioi.teachers.controllers.TeacherContestController'
Expand All @@ -28,7 +31,8 @@ def test_problemset_permissions(self):
response = self.client.get(url_add, follow=True)
self.assertEqual(response.status_code, 200)

self.assertTrue(self.client.login(username='test_user2')) # test_user2 is not
self.assertTrue(
self.client.login(username='test_user2')) # test_user2 is not
response = self.client.get(url_main)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'Add problem')
Expand Down Expand Up @@ -181,3 +185,36 @@ def test_teacher_modify(self):
self.assertEqual(Teacher.objects.all().count(), 2)
mod_teacher = Teacher.objects.get(pk=1001)
self.assertEqual(mod_teacher.school, "New School")


class TestAddUserToContestForm(TestCase):
fixtures = ['test_users', 'teachers', 'test_contest']

def setUp(self):
self.user = User.objects.get(username='test_user')
self.c = Contest.objects.get(id='c')

def test_add_user_to_contest_as_pupil(self):
self.assertEqual(add_res.Added, autc(self.user, self.c, 'pupil'))
self.assertEqual(add_res.UserIsAlreadyAdded,
autc(self.user, self.c, 'pupil'))
self.assertEqual(add_res.UserIsAlreadyAdded,
autc(self.user, self.c, 'teacher'))

def test_add_user_to_contest_as_teacher(self):
self.assertEqual(add_res.Added, autc(self.user, self.c, 'teacher'))
self.assertEqual(add_res.UserIsAlreadyAdded,
autc(self.user, self.c, 'pupil'))
self.assertEqual(add_res.UserIsAlreadyAdded,
autc(self.user, self.c, 'teacher'))

def test_add_non_teacher_as_teacher(self):
not_teacher = User.objects.filter(is_superuser=False,
teacher__isnull=True,
is_active=True).first()

self.assertEqual(add_res.UserIsNotATeacher,
autc(not_teacher, self.c, 'teacher'))
self.assertEqual(add_res.Added, autc(not_teacher, self.c, 'pupil'))
self.assertEqual(add_res.UserIsAlreadyAdded,
autc(not_teacher, self.c, 'teacher'))
4 changes: 4 additions & 0 deletions oioioi/teachers/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
name='teachers_regenerate_key',
),
re_path(r'^delete/$', views.delete_members_view, name='teachers_delete_members'),


re_path(r'^registration/add_user/$', views.add_user_to_contest, name='teachers_add_user_to_contest'),
re_path(r'^registration/get_appendable_users/$', views.get_appendable_users_view, name='teachers_get_appendable_users'),
]

contest_patterns = [
Expand Down
51 changes: 51 additions & 0 deletions oioioi/teachers/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from enum import Enum

from oioioi.participants.models import Participant
from oioioi.teachers.models import ContestTeacher, Teacher


def get_user_teacher_obj(user):
try:
return user.teacher
except Teacher.DoesNotExist:
return None


def is_user_already_in_contest(user, contest):
teacher = get_user_teacher_obj(user)

if user.participant_set.filter(contest=contest) or \
teacher and teacher.contestteacher_set.filter(contest=contest):
return True

return False


class UserAddResult(Enum):
Added = 1
UserIsAlreadyAdded = 2
UserIsNotATeacher = 3


def add_user_to_contest_as(user, contest, member_type) -> UserAddResult:
if is_user_already_in_contest(user, contest):
return UserAddResult.UserIsAlreadyAdded

created = False
if member_type == 'pupil':
_p, created = Participant.objects.get_or_create(
contest=contest, user=user
)

elif member_type == 'teacher':
if teacher := get_user_teacher_obj(user):
_ct, created = ContestTeacher.objects.get_or_create(
contest=contest, teacher=teacher
)
else:
return UserAddResult.UserIsNotATeacher

if created:
return UserAddResult.Added
else:
return UserAddResult.UserIsAlreadyAdded
33 changes: 32 additions & 1 deletion oioioi/teachers/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
from oioioi.contests.utils import contest_exists, is_contest_admin
from oioioi.participants.models import Participant
from oioioi.teachers.controllers import TeacherContestController
from oioioi.teachers.forms import AddTeacherForm
from oioioi.teachers.forms import AddTeacherForm, AddUserToContestForm
from oioioi.teachers.models import ContestTeacher, RegistrationConfig, Teacher
from oioioi.teachers.utils import is_user_already_in_contest, get_user_teacher_obj, add_user_to_contest_as, \
UserAddResult

if 'oioioi.usergroups' in settings.INSTALLED_APPS:
import oioioi.usergroups.utils as usergroups
Expand Down Expand Up @@ -398,3 +400,32 @@ def contest_dashboard_redirect(request):
kwargs={'contest_id': request.contest.id},
)
)


@enforce_condition(is_teachers_contest & is_contest_admin)
def get_appendable_users_view(request, member_type):
users = User.objects.filter(is_superuser=False, is_active=True)
if member_type == 'teacher':
users = users.filter(teacher__isnull=False)

return get_user_hints_view(request, 'substr', users)


@require_POST
@enforce_condition(contest_exists & is_teachers_contest & is_contest_admin)
def add_user_to_contest(request, member_type):
form = AddUserToContestForm(request.POST)
if form.is_valid():
user = form.cleaned_data['user']

result = add_user_to_contest_as(user, request.contest, member_type)
if result == UserAddResult.UserIsAlreadyAdded:
messages.error(request, _("User \'{}\' is already added.".format(user)))
elif result == UserAddResult.UserIsNotATeacher:
messages.error(request, _("User \'{}\' is not a teacher!".format(user)))
else:
messages.success(request, _("Successfully added \'{}\' as a {}.".format(user, member_type)))
else:
messages.error(request, _('There is no user \'{}\'.'.format(form.data['user'])))

return redirect_to_members(request, member_type)
Loading