1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2024-12-25 07:02:22 +00:00

Add & join teams

This commit is contained in:
Yohann D'ANELLO 2020-05-05 00:56:34 +02:00
parent b55aa6f4f3
commit 3889256fb1
8 changed files with 82 additions and 24 deletions

View File

@ -141,7 +141,7 @@ class TFJMUser(AbstractUser):
@property
def participates(self):
return self.role == "3participant" or self.role == "2encadrant"
return self.role == "3participant" or self.role == "2coach"
@property
def organizes(self):

View File

@ -1,9 +1,20 @@
import django_tables2 as tables
from django_tables2 import A
from member.models import TFJMUser
class UserTable(tables.Table):
last_name = tables.LinkColumn(
"member:information",
args=[A("pk")],
)
first_name = tables.LinkColumn(
"member:information",
args=[A("pk")],
)
class Meta:
model = TFJMUser
fields = ("last_name", "first_name", "role", "date_joined", )

View File

@ -1,7 +1,6 @@
from django.urls import path
from django.views.generic import RedirectView
from .views import CreateUserView, MyAccountView, UserDetailView, MyTeamView,\
from .views import CreateUserView, MyAccountView, UserDetailView, AddTeamView, JoinTeamView, MyTeamView,\
ProfileListView, OrphanedProfileListView, OrganizersListView, ResetAdminView
app_name = "member"
@ -10,10 +9,9 @@ urlpatterns = [
path('signup/', CreateUserView.as_view(), name="signup"),
path("my-account/", MyAccountView.as_view(), name="my_account"),
path("information/<int:pk>/", UserDetailView.as_view(), name="information"),
path("add-team/", RedirectView.as_view(pattern_name="index"), name="add_team"),
path("join-team/", RedirectView.as_view(pattern_name="index"), name="join_team"),
path("add-team/", AddTeamView.as_view(), name="add_team"),
path("join-team/", JoinTeamView.as_view(), name="join_team"),
path("my-team/", MyTeamView.as_view(), name="my_team"),
path("my-team/update/", RedirectView.as_view(pattern_name="index"), name="update_my_team"),
path("profiles/", ProfileListView.as_view(), name="all_profiles"),
path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"),
path("organizers/", OrganizersListView.as_view(), name="organizers"),

View File

@ -1,14 +1,18 @@
import random
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.http import FileResponse
from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views import View
from django.views.generic import CreateView, UpdateView, DetailView
from django.views.generic import CreateView, UpdateView, DetailView, FormView
from django_tables2 import SingleTableView
from tournament.forms import TeamForm, JoinTeam
from tournament.models import Team
from tournament.views import AdminMixin, TeamMixin
from .forms import SignUpForm, TFJMUserForm
@ -65,28 +69,49 @@ class UserDetailView(LoginRequiredMixin, DetailView):
return context
class MyTeamView(TeamMixin, DetailView):
class AddTeamView(LoginRequiredMixin, CreateView):
model = Team
form_class = TeamForm
def get_object(self, queryset=None):
return self.request.user.team
def form_valid(self, form):
team = form.instance
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
code = ""
for _ in range(6):
code += random.choice(alphabet)
team.access_code = code
team.validation_status = "0invalid"
def dispatch(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
raise PermissionDenied
team.save()
team.refresh_from_db()
team = self.get_object()
self.request.user.team = team
self.request.user.save()
if not request.user.participates or team is None:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
def get_success_url(self):
return reverse_lazy("member:my_team")
context["title"] = str(self.object)
return context
class JoinTeamView(LoginRequiredMixin, FormView):
model = Team
form_class = JoinTeam
template_name = "tournament/team_form.html"
def form_valid(self, form):
team = form.cleaned_data["team"]
self.request.user.team = team
self.request.user.save()
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("member:my_team")
class MyTeamView(TeamMixin, View):
def get(self, request, *args, **kwargs):
return redirect("tournament:team_detail", pk=request.user.team.pk)
class DocumentView(LoginRequiredMixin, View):

View File

@ -43,6 +43,16 @@ class JoinTeam(forms.Form):
max_length=6,
)
def clean(self):
cleaned_data = super().clean()
team = Team.objects.filter(access_code=cleaned_data["access_code"])
if not team.exists():
self.add_error('access_code', _("This access code is invalid."))
cleaned_data["team"] = team.get()
return cleaned_data
class SolutionForm(forms.ModelForm):
problem = forms.ChoiceField(

View File

@ -14,7 +14,7 @@ from django.views.generic.edit import BaseFormView
from django_tables2.views import SingleTableView
from member.models import TFJMUser, Solution, Synthesis
from .forms import TournamentForm, OrganizerForm, TeamForm, SolutionForm, SynthesisForm
from .forms import TournamentForm, OrganizerForm, SolutionForm, SynthesisForm, TeamForm
from .models import Tournament, Team
from .tables import TournamentTable, TeamTable, SolutionTable, SynthesisTable
@ -128,6 +128,12 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
.format(_("Solutions for team {team}.zip")
.format(team=str(team)).replace(" ", "%20"))
return resp
elif "leave" in request.POST:
request.user.team = None
request.user.save()
if not team.users.exists():
team.delete()
return redirect('tournament:detail', pk=team.tournament.pk)
elif "delete" in request.POST:
team.delete()
return redirect('tournament:detail', pk=team.tournament.pk)

View File

@ -89,7 +89,7 @@
<a class="nav-link" href="{% url "member:my_account" %}"><i class="fas fa-user"></i> {% trans "My account" %}</a>
</li>
{% if user.participates %}
{% if user.team is None %}
{% if not user.team %}
<li class="nav-item active">
<a class="nav-link" href="{% url "member:add_team" %}"><i class="fas fa-folder-plus"></i> {% trans "Add a team" %}</a>
</li>

View File

@ -15,6 +15,9 @@
<dt class="col-xl-6 text-right">{% trans 'trigram'|capfirst %}</dt>
<dd class="col-xl-6">{{ team.trigram }}</dd>
<dt class="col-xl-6 text-right">{% trans 'access code'|capfirst %}</dt>
<dd class="col-xl-6">{{ team.access_code }}</dd>
<dt class="col-xl-6 text-right">{% trans 'tournament'|capfirst %}</dt>
<dd class="col-xl-6"><a href="{% url "tournament:detail" pk=team.tournament.pk %}">{{ team.tournament }}</a></dd>
@ -23,12 +26,17 @@
<dt class="col-xl-6 text-right">{% trans 'participants'|capfirst %}</dt>
<dd class="col-xl-6">{% autoescape off %}{{ team.linked_participants|join:", " }}{% endautoescape %}</dd>
<dt class="col-xl-6 text-right">{% trans 'validation status'|capfirst %}</dt>
<dd class="col-xl-6">{{ team.get_validation_status_display }}</dd>
</dl>
</div>
{% if user.admin or user in team.tournament.organizers.all or team == user.team %}
<div class="card-footer text-center">
{% if team.invalid or user.organizes %}
<a href="{% url "tournament:team_update" pk=team.pk %}"><button class="btn btn-secondary">{% trans "Edit team" %}</button></a>
{% endif %}
{% if team.invalid %}
<form method="post">
{% csrf_token %}