Create team detail page

This commit is contained in:
Yohann D'ANELLO 2020-09-24 10:21:50 +02:00
parent cce3a0a7df
commit 8c70ef3835
8 changed files with 222 additions and 107 deletions

View File

@ -1,5 +1,10 @@
from django.apps import AppConfig
from django.db.models.signals import post_save
class ParticipationConfig(AppConfig):
name = 'participation'
def ready(self):
from participation.signals import create_team_participation
post_save.connect(create_team_participation, "participation.Team")

View File

@ -0,0 +1,5 @@
from participation.models import Participation
def create_team_participation(instance, **_):
Participation.objects.get_or_create(team=instance)

View File

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
{% trans "any" as any %}
<div class="card bg-light shadow">
<div class="card-header text-center">
<h4>{{ team.name }}</h4>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-6 text-right">{% trans "Name:" %}</dt>
<dd class="col-sm-6">{{ team.name }}</dd>
<dt class="col-sm-6 text-right">{% trans "Trigram:" %}</dt>
<dd class="col-sm-6">{{ team.trigram }}</dd>
<dt class="col-sm-6 text-right">{% trans "Access code:" %}</dt>
<dd class="col-sm-6">{{ team.access_code }}</dd>
<dt class="col-sm-6 text-right">{% trans "Coachs:" %}</dt>
<dd class="col-sm-6">{{ team.coachs.all|join:", "|default:any }}</dd>
<dt class="col-sm-6 text-right">{% trans "Participants:" %}</dt>
<dd class="col-sm-6">{{ team.students.all|join:", "|default:any }}</dd>
<dt class="col-sm-6 text-right">{% trans "Chosen problem:" %}</dt>
<dd class="col-sm-6">{{ team.participation.problem|default:any }}</dd>
</dl>
</div>
</div>
{% endblock %}

View File

@ -1,6 +1,6 @@
from django.urls import path
from .views import CreateTeamView, JoinTeamView
from .views import CreateTeamView, JoinTeamView, MyTeamDetailView, TeamDetailView
app_name = "participation"
@ -8,4 +8,6 @@ app_name = "participation"
urlpatterns = [
path("create_team/", CreateTeamView.as_view(), name="create_team"),
path("join_team/", JoinTeamView.as_view(), name="join_team"),
path("team/", MyTeamDetailView.as_view(), name="my_team_detail"),
path("team/<int:pk>/", TeamDetailView.as_view(), name="team_detail"),
]

View File

@ -1,8 +1,9 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, FormView
from django.views.generic import CreateView, FormView, DetailView, RedirectView
from participation.forms import TeamForm, JoinTeamForm
from participation.models import Team
@ -58,3 +59,18 @@ class JoinTeamView(LoginRequiredMixin, FormView):
def get_success_url(self):
return reverse_lazy("index")
class MyTeamDetailView(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
user = self.request.user
registration = user.registration
if registration.participates:
if registration.team:
return reverse_lazy("participation:team_detail", args=(registration.team_id,))
raise PermissionDenied(_("You are not in a team."))
raise PermissionDenied(_("You don't participate, so you don't have any team."))
class TeamDetailView(LoginRequiredMixin, DetailView):
model = Team

View File

@ -56,8 +56,7 @@ class Registration(PolymorphicModel):
return isinstance(self, StudentRegistration) or isinstance(self, CoachRegistration)
def __str__(self):
return _("registration of {first_name} {last_name}")\
.format(first_name=self.user.first_name, last_name=self.user.last_name)
return f"{self.user.first_name} {self.user.last_name}"
class Meta:
verbose_name = _("registration")

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Corres2math\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-09-22 21:26+0200\n"
"POT-Creation-Date: 2020-09-24 09:53+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -101,35 +101,35 @@ msgstr "changelogs"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
#: apps/participation/forms.py:14 apps/participation/models.py:18
msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules."
#: apps/participation/forms.py:26
msgid "No team was found with this access code."
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
#: apps/participation/models.py:10
#: apps/participation/models.py:11
msgid "name"
msgstr "nom"
#: apps/participation/models.py:16
#: apps/participation/models.py:17
msgid "trigram"
msgstr "trigramme"
#: apps/participation/models.py:17
msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules."
#: apps/participation/models.py:24
#: apps/participation/models.py:25
msgid "access code"
msgstr "code d'accès"
#: apps/participation/models.py:25
#: apps/participation/models.py:26
msgid "The access code let other people to join the team."
msgstr "Le code d'accès permet aux autres participants de rejoindre l'équipe."
#: apps/participation/models.py:29
#: apps/participation/models.py:30
msgid "Grant Animath to publish my video"
msgstr "Autoriser Animath à publier ma vidéo"
#: apps/participation/models.py:30
#: apps/participation/models.py:31
msgid ""
"Give the authorisation to publish the video on the main website to promote "
"the action."
@ -137,80 +137,80 @@ msgstr ""
"Donner l'autorisation de publier la vidéo sur le site principal pour "
"promouvoir les Correspondances."
#: apps/participation/models.py:35
#: apps/participation/models.py:41
#, python-brace-format
msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})"
#: apps/participation/models.py:38 apps/participation/models.py:49
#: apps/registration/models.py:78 apps/registration/models.py:111
#: apps/participation/models.py:44 apps/participation/models.py:55
#: apps/registration/models.py:73 apps/registration/models.py:106
msgid "team"
msgstr "équipe"
#: apps/participation/models.py:39
#: apps/participation/models.py:45
msgid "teams"
msgstr "équipes"
#: apps/participation/models.py:53
#: apps/participation/models.py:59
#, python-brace-format
msgid "Problem #{problem:d}"
msgstr "Problème n°{problem:d}"
#: apps/participation/models.py:56
#: apps/participation/models.py:62
msgid "problem number"
msgstr "numéro de problème"
#: apps/participation/models.py:65
#: apps/participation/models.py:71
msgid "solution video"
msgstr "vidéo de solution"
#: apps/participation/models.py:74
#: apps/participation/models.py:80
msgid "received participation"
msgstr "participation reçue"
#: apps/participation/models.py:83
#: apps/participation/models.py:89
msgid "synthesis video"
msgstr "vidéo de synthèse"
#: apps/participation/models.py:87
#: apps/participation/models.py:93
#, python-brace-format
msgid "Participation of the team {name} ({trigram})"
msgstr "Participation de l'équipe {name} ({trigram})"
#: apps/participation/models.py:90 apps/participation/models.py:98
#: apps/participation/models.py:96 apps/participation/models.py:104
msgid "participation"
msgstr "participation"
#: apps/participation/models.py:91
#: apps/participation/models.py:97
msgid "participations"
msgstr "participations"
#: apps/participation/models.py:102
#: apps/participation/models.py:108
msgid "link"
msgstr "lien"
#: apps/participation/models.py:103
#: apps/participation/models.py:109
msgid "The full video link."
msgstr "Le lien complet de la vidéo."
#: apps/participation/models.py:109
#: apps/participation/models.py:115
msgid "valid"
msgstr "valide"
#: apps/participation/models.py:110
#: apps/participation/models.py:116
msgid "The video got the validation of the administrators."
msgstr "La vidéo a été validée par les administrateurs."
#: apps/participation/models.py:114
#: apps/participation/models.py:120
#, python-brace-format
msgid "Video of team {name} ({trigram})"
msgstr "Vidéo de l'équipe {name} ({trigram})"
#: apps/participation/models.py:118
#: apps/participation/models.py:124
msgid "video"
msgstr "vidéo"
#: apps/participation/models.py:119
#: apps/participation/models.py:125
msgid "videos"
msgstr "vidéos"
@ -220,7 +220,7 @@ msgid "Create"
msgstr "Créer"
#: apps/participation/templates/participation/create_team_modal.html:8
#: apps/participation/views.py:12 templates/base.html:75
#: apps/participation/views.py:15 templates/base.html:76
msgid "Create team"
msgstr "Créer une équipe"
@ -230,10 +230,54 @@ msgid "Join"
msgstr "Rejoindre"
#: apps/participation/templates/participation/join_team_modal.html:8
#: apps/participation/views.py:19 templates/base.html:80
#: apps/participation/views.py:41 templates/base.html:81
msgid "Join team"
msgstr "Rejoindre une équipe"
#: apps/participation/templates/participation/team_detail.html:6
msgid "any"
msgstr "aucun"
#: apps/participation/templates/participation/team_detail.html:14
msgid "Name:"
msgstr "Nom :"
#: apps/participation/templates/participation/team_detail.html:17
msgid "Trigram:"
msgstr "Trigramme :"
#: apps/participation/templates/participation/team_detail.html:20
msgid "Access code:"
msgstr "Code d'accès :"
#: apps/participation/templates/participation/team_detail.html:23
msgid "Coachs:"
msgstr "Encadrants :"
#: apps/participation/templates/participation/team_detail.html:26
msgid "Participants:"
msgstr "Participants :"
#: apps/participation/templates/participation/team_detail.html:29
msgid "Chosen problem:"
msgstr "Problème choisi :"
#: apps/participation/views.py:23 apps/participation/views.py:49
msgid "You don't participate, so you can't create a team."
msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe."
#: apps/participation/views.py:26 apps/participation/views.py:52
msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe."
#: apps/participation/views.py:71
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
#: apps/participation/views.py:72
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
#: apps/registration/forms.py:11
msgid "role"
msgstr "rôle"
@ -242,7 +286,7 @@ msgstr "rôle"
msgid "participant"
msgstr "participant"
#: apps/registration/forms.py:14 apps/registration/models.py:120
#: apps/registration/forms.py:14 apps/registration/models.py:115
msgid "coach"
msgstr "encadrant"
@ -255,80 +299,75 @@ msgstr ""
msgid "email confirmed"
msgstr "email confirmé"
#: apps/registration/models.py:34
#: apps/registration/models.py:30
msgid "Activate your Correspondances account"
msgstr "Activez votre compte des Correspondances"
#: apps/registration/models.py:63
#, python-brace-format
msgid "registration of {first_name} {last_name}"
msgstr "inscription de {first_name} {last_name}"
#: apps/registration/models.py:67
#: apps/registration/models.py:62
msgid "registration"
msgstr "inscription"
#: apps/registration/models.py:68
#: apps/registration/models.py:63
msgid "registrations"
msgstr "inscriptions"
#: apps/registration/models.py:83
#: apps/registration/models.py:78
msgid "12th grade"
msgstr "Terminale"
#: apps/registration/models.py:84
#: apps/registration/models.py:79
msgid "11th grade"
msgstr "Première"
#: apps/registration/models.py:85
#: apps/registration/models.py:80
msgid "10th grade or lower"
msgstr "Seconde ou inférieur"
#: apps/registration/models.py:87
#: apps/registration/models.py:82
msgid "student class"
msgstr "classe"
#: apps/registration/models.py:92
#: apps/registration/models.py:87
msgid "school"
msgstr "école"
#: apps/registration/models.py:97
#: apps/registration/models.py:92
msgid "student"
msgstr "étudiant"
#: apps/registration/models.py:100
#: apps/registration/models.py:95
msgid "student registration"
msgstr "inscription d'élève"
#: apps/registration/models.py:101
#: apps/registration/models.py:96
msgid "student registrations"
msgstr "inscriptions d'élève"
#: apps/registration/models.py:115
#: apps/registration/models.py:110
msgid "professional activity"
msgstr "activité professionnelle"
#: apps/registration/models.py:123
#: apps/registration/models.py:118
msgid "coach registration"
msgstr "inscription d'encadrant"
#: apps/registration/models.py:124
#: apps/registration/models.py:119
msgid "coach registrations"
msgstr "inscriptions d'encadrants"
#: apps/registration/models.py:129
#: apps/registration/models.py:124
msgid "role of the administrator"
msgstr "rôle de l'administrateur"
#: apps/registration/models.py:134
#: apps/registration/models.py:129
msgid "admin"
msgstr "admin"
#: apps/registration/models.py:137
#: apps/registration/models.py:132
msgid "admin registration"
msgstr "inscription d'administrateur"
#: apps/registration/models.py:138
#: apps/registration/models.py:133
msgid "admin registrations"
msgstr "inscriptions d'administrateur"
@ -371,7 +410,7 @@ msgstr "Se reconnecter"
#: apps/registration/templates/registration/login_modal.html:8
#: apps/registration/templates/registration/login_modal.html:15
#: apps/registration/templates/registration/password_reset_complete.html:10
#: templates/base.html:106 templates/registration/login.html:7
#: templates/base.html:114 templates/registration/login.html:7
#: templates/registration/login.html:8 templates/registration/login.html:25
msgid "Log in"
msgstr "Connexion"
@ -569,31 +608,35 @@ msgstr ""
msgid "Home"
msgstr "Accueil"
#: templates/base.html:86
#: templates/base.html:87
msgid "My team"
msgstr "Mon équipe"
#: templates/base.html:94
msgid "Make a gift"
msgstr "Faire un don"
#: templates/base.html:90
#: templates/base.html:98
msgid "Administration"
msgstr "Administration"
#: templates/base.html:97
#: templates/base.html:105
msgid "Return to admin view"
msgstr "Retourner à l'interface administrateur"
#: templates/base.html:102
#: templates/base.html:110
msgid "Register"
msgstr "S'inscrire"
#: templates/base.html:111
#: templates/base.html:119
msgid "Log out"
msgstr "Déconnexion"
#: templates/base.html:137
#: templates/base.html:145
msgid "Contact us"
msgstr "Nous contacter"
#: templates/base.html:160
#: templates/base.html:168
msgid "Back to top"
msgstr "Retour en haut"

View File

@ -1,7 +1,8 @@
{% load static i18n static %}
<!DOCTYPE html>
<html lang="en" class="position-relative h-100">
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %} class="position-relative h-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@ -43,13 +44,6 @@
{{ form.media }}
{% endif %}
<style>
.validate:hover {
cursor: pointer;
text-decoration: underline;
}
</style>
{% block extracss %}{% endblock %}
</head>
<body class="d-flex w-100 h-100 flex-column">
@ -65,21 +59,29 @@
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbarNavDropdown" class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<ul class="navbar-nav">
<li class="nav-item active">
<a href="{% url "index" %}" class="nav-link"><i class="fas fa-home"></i> {% trans "Home" %}</a>
</li>
{% if user.is_authenticated and user.registration.participates and not user.registration.team %}
<li class="nav-item active">
<a href="#" class="nav-link" data-toggle="modal" data-target="#createTeamModal">
<i class="fas fa-users"></i> {% trans "Create team" %}
</a>
</li>
<li class="nav-item active">
<a href="#" class="nav-link" data-toggle="modal" data-target="#joinTeamModal">
<i class="fas fa-users"></i> {% trans "Join team" %}
</a>
</li>
{% if user.is_authenticated and user.registration.participates %}
{% if not user.registration.team %}
<li class="nav-item active">
<a href="#" class="nav-link" data-toggle="modal" data-target="#createTeamModal">
<i class="fas fa-users"></i> {% trans "Create team" %}
</a>
</li>
<li class="nav-item active">
<a href="#" class="nav-link" data-toggle="modal" data-target="#joinTeamModal">
<i class="fas fa-users"></i> {% trans "Join team" %}
</a>
</li>
{% else %}
<li class="nav-item active">
<a href="{% url "participation:my_team_detail" %}" class="nav-link">
<i class="fas fa-users"></i> {% trans "My team" %}
</a>
</li>
{% endif %}
{% endif %}
<li class="nav-item active">
<a class="nav-link" href="https://www.helloasso.com/associations/animath/formulaires/5/widget"><i
@ -91,7 +93,7 @@
</li>
{% endif %}
</ul>
<ul class="navbar-nav">
<ul class="navbar-nav ml-auto">
{% if "_fake_user_id" in request.session %}
<li class="nav-item active">
<a class="nav-link" href="{% url "member:reset_admin" %}?path={{ request.path }}"><i class="fas fa-tools"></i> {% trans "Return to admin view" %}</a>
@ -107,15 +109,24 @@
</a>
</li>
{% else %}
<li class="nav-item active">
<a class="nav-link" href="{% url "logout" %}"><i class="fas fa-sign-out-alt"></i> {% trans "Log out" %}</a>
<li class="dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-user"></i> {{ user.first_name }} {{ user.last_name }}
</a>
<div class="dropdown-menu dropdown-menu-right"
aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="{% url "logout" %}">
<i class="fas fa-sign-out-alt"></i> {% trans "Log out" %}
</a>
</div>
</li>
{% endif %}
</ul>
</div>
</nav>
<div class="container-fluid my-3" style="max-width: 1600px;">
{% block contenttitle %}<h1>{{ title }}</h1>{% endblock %}
<div class="{% block containertype %}container{% endblock %} my-3">
{% block contenttitle %}{% endblock %}
<div id="messages"></div>
<div id="content">
{% block content %}
@ -125,29 +136,27 @@
</div>
</main>
<footer class="bg-light mt-auto py-2">
<footer class="bg-light text-primary mt-auto py-2">
<div class="container-fluid">
<div class="row">
<div class="col-sm">
<div class="col-10">
<form action="{% url 'set_language' %}" method="post"
class="form-inline">
<span class="text-muted mr-1">
<img src="{% static "logo.png" %}" style="width: 42px;" /> &mdash;
<a href="mailto:contact@correspondances-maths.fr"
<a href="mailto:contact&#64;correspondances-maths.fr"
class="text-muted">{% trans "Contact us" %}</a> &mdash;
</span>
{% csrf_token %}
<select title="language" name="language"
class="custom-select custom-select-sm"
class="form-control form-control-sm language"
onchange="this.form.submit()">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"
{% if language.code == LANGUAGE_CODE %}
{% for lang_code, lang_name in LANGUAGES %}
<option value="{{ lang_code }}"
{% if lang_code == LANGUAGE_CODE %}
selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
{{ lang_name }} ({{ lang_code }})
</option>
{% endfor %}
</select>
@ -156,8 +165,10 @@
</noscript>
</form>
</div>
<div class="col-sm text-right">
<a href="#" data-turbolinks="false" class="text-muted">{% trans "Back to top" %}</a>
<div class="col text-right">
<a href="#" data-turbolinks="false" class="text-muted">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</a>
</div>
</div>
</div>
@ -171,6 +182,7 @@
<script>
CSRF_TOKEN = "{{ csrf_token }}";
$(".invalid-feedback").addClass("d-block");
$(document).ready(function () {
$('a[data-target="#loginModal"]').click(function() {
@ -191,7 +203,6 @@
});
</script>
{% block extrajavascript %}
{% endblock extrajavascript %}
{% block extrajavascript %}{% endblock %}
</body>
</html>