diff --git a/apps/participation/forms.py b/apps/participation/forms.py
index 7d17e5f..cce1358 100644
--- a/apps/participation/forms.py
+++ b/apps/participation/forms.py
@@ -3,11 +3,13 @@
import re
+from bootstrap_datepicker_plus import DatePickerInput, DateTimePickerInput
from django import forms
from django.core.exceptions import ValidationError
+from django.utils import formats
from django.utils.translation import gettext_lazy as _
-from .models import Participation, Team
+from .models import Participation, Team, Tournament
class TeamForm(forms.ModelForm):
@@ -85,3 +87,25 @@ class ValidateParticipationForm(forms.Form):
label=_("Message to address to the team:"),
widget=forms.Textarea(),
)
+
+
+class TournamentForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ self.fields["date_start"].widget = DatePickerInput(
+ format=formats.get_format_lazy(format_type="DATE_INPUT_FORMATS", use_l10n=True)[0])
+ self.fields["date_end"].widget = DatePickerInput(
+ format=formats.get_format_lazy(format_type="DATE_INPUT_FORMATS", use_l10n=True)[0])
+ self.fields["inscription_limit"].widget = DateTimePickerInput(
+ format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0])
+ self.fields["solution_limit"].widget = DateTimePickerInput(
+ format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0])
+ self.fields["syntheses_first_phase_limit"].widget = DateTimePickerInput(
+ format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0])
+ self.fields["syntheses_second_phase_limit"].widget = DateTimePickerInput(
+ format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0])
+
+ class Meta:
+ model = Tournament
+ fields = '__all__'
diff --git a/apps/participation/migrations/0001_initial.py b/apps/participation/migrations/0001_initial.py
index 5a646c4..8807016 100644
--- a/apps/participation/migrations/0001_initial.py
+++ b/apps/participation/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.1.4 on 2020-12-28 17:16
+# Generated by Django 3.0.11 on 2020-12-30 12:02
import django.core.validators
from django.db import migrations, models
@@ -79,7 +79,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True, verbose_name='name')),
('date_start', models.DateField(default=django.utils.timezone.now, verbose_name='start')),
- ('date_end', models.DateField(default=django.utils.timezone.now, verbose_name='start')),
+ ('date_end', models.DateField(default=django.utils.timezone.now, verbose_name='end')),
('inscription_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date for registrations')),
('solution_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date to upload solutions')),
('syntheses_first_phase_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date to upload the syntheses for the first phase')),
diff --git a/apps/participation/migrations/0002_auto_20201228_1816.py b/apps/participation/migrations/0002_auto_20201230_1302.py
similarity index 79%
rename from apps/participation/migrations/0002_auto_20201228_1816.py
rename to apps/participation/migrations/0002_auto_20201230_1302.py
index f9e165a..afa485f 100644
--- a/apps/participation/migrations/0002_auto_20201228_1816.py
+++ b/apps/participation/migrations/0002_auto_20201230_1302.py
@@ -1,5 +1,6 @@
-# Generated by Django 3.1.4 on 2020-12-28 17:16
+# Generated by Django 3.0.11 on 2020-12-30 12:02
+import address.models
from django.db import migrations, models
import django.db.models.deletion
@@ -9,8 +10,9 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
- ('participation', '0001_initial'),
('registration', '0001_initial'),
+ ('address', '0003_auto_20200830_1851'),
+ ('participation', '0001_initial'),
]
operations = [
@@ -19,6 +21,11 @@ class Migration(migrations.Migration):
name='organizers',
field=models.ManyToManyField(related_name='organized_tournaments', to='registration.VolunteerRegistration', verbose_name='organizers'),
),
+ migrations.AddField(
+ model_name='tournament',
+ name='place',
+ field=address.models.AddressField(on_delete=django.db.models.deletion.CASCADE, to='address.Address', verbose_name='place'),
+ ),
migrations.AddIndex(
model_name='team',
index=models.Index(fields=['trigram'], name='participati_trigram_239255_idx'),
@@ -26,17 +33,17 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='synthesis',
name='participation',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.participation', verbose_name='participation'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.Participation', verbose_name='participation'),
),
migrations.AddField(
model_name='synthesis',
name='pool',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.pool', verbose_name='pool'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.Pool', verbose_name='pool'),
),
migrations.AddField(
model_name='solution',
name='participation',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='solutions', to='participation.participation', verbose_name='participation'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='solutions', to='participation.Participation', verbose_name='participation'),
),
migrations.AddField(
model_name='pool',
@@ -51,17 +58,17 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='pool',
name='tournament',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pools', to='participation.tournament', verbose_name='tournament'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pools', to='participation.Tournament', verbose_name='tournament'),
),
migrations.AddField(
model_name='participation',
name='team',
- field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='participation.team', verbose_name='team'),
+ field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='participation.Team', verbose_name='team'),
),
migrations.AddField(
model_name='participation',
name='tournament',
- field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='participation.tournament', verbose_name='tournament'),
+ field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='participation.Tournament', verbose_name='tournament'),
),
migrations.AddIndex(
model_name='tournament',
diff --git a/apps/participation/models.py b/apps/participation/models.py
index 647530d..05113b7 100644
--- a/apps/participation/models.py
+++ b/apps/participation/models.py
@@ -3,6 +3,7 @@
import os
+from address.models import AddressField
from django.core.validators import RegexValidator
from django.db import models
from django.db.models import Index
@@ -133,6 +134,10 @@ class Tournament(models.Model):
default=timezone.now,
)
+ place = AddressField(
+ verbose_name=_("place"),
+ )
+
inscription_limit = models.DateTimeField(
verbose_name=_("limit date for registrations"),
default=timezone.now,
diff --git a/apps/participation/templates/participation/tournament_form.html b/apps/participation/templates/participation/tournament_form.html
new file mode 100644
index 0000000..1c93537
--- /dev/null
+++ b/apps/participation/templates/participation/tournament_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% load crispy_forms_filters i18n %}
+
+{% block content %}
+
+{% endblock content %}
diff --git a/apps/participation/templates/participation/tournament_list.html b/apps/participation/templates/participation/tournament_list.html
index 70a79d7..860342d 100644
--- a/apps/participation/templates/participation/tournament_list.html
+++ b/apps/participation/templates/participation/tournament_list.html
@@ -10,7 +10,7 @@
{% endblock %}
diff --git a/apps/participation/urls.py b/apps/participation/urls.py
index e02cb6e..ae45494 100644
--- a/apps/participation/urls.py
+++ b/apps/participation/urls.py
@@ -6,7 +6,8 @@ from django.views.generic import TemplateView
from .views import CreateTeamView, JoinTeamView, \
MyParticipationDetailView, MyTeamDetailView, ParticipationDetailView, TeamAuthorizationsView, \
- TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, TournamentListView
+ TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, TournamentCreateView, TournamentDetailView, \
+ TournamentListView, TournamentUpdateView
app_name = "participation"
@@ -23,5 +24,8 @@ urlpatterns = [
path("detail/", MyParticipationDetailView.as_view(), name="my_participation_detail"),
path("detail//", ParticipationDetailView.as_view(), name="participation_detail"),
path("tournament/", TournamentListView.as_view(), name="tournament_list"),
+ path("tournament/create/", TournamentCreateView.as_view(), name="tournament_create"),
+ path("tournament//", TournamentDetailView.as_view(), name="tournament_detail"),
+ path("tournament//update/", TournamentUpdateView.as_view(), name="tournament_update"),
path("chat/", TemplateView.as_view(template_name="participation/chat.html"), name="chat")
]
diff --git a/apps/participation/views.py b/apps/participation/views.py
index cc567e1..c75d05d 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -23,7 +23,8 @@ from tfjm.lists import get_sympa_client
from tfjm.matrix import Matrix
from tfjm.views import AdminMixin
-from .forms import JoinTeamForm, ParticipationForm, RequestValidationForm, TeamForm, ValidateParticipationForm
+from .forms import JoinTeamForm, ParticipationForm, RequestValidationForm, TeamForm, ValidateParticipationForm, \
+ TournamentForm
from .models import Participation, Team, Tournament
from .tables import TeamTable, TournamentTable
@@ -404,5 +405,37 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView):
class TournamentListView(SingleTableView):
+ """
+ Display the list of all tournaments.
+ """
model = Tournament
table_class = TournamentTable
+
+
+class TournamentCreateView(AdminMixin, CreateView):
+ """
+ Create a new tournament.
+ """
+ model = Tournament
+ form_class = TournamentForm
+
+ def get_success_url(self):
+ return reverse_lazy("participation:tournament_detail", args=(self.object.pk,))
+
+
+class TournamentUpdateView(AdminMixin, UpdateView):
+ """
+ Update tournament detail.
+ """
+ model = Tournament
+ form_class = TournamentForm
+
+ def get_success_url(self):
+ return reverse_lazy("participation:tournament_detail", args=(self.object.pk,))
+
+
+class TournamentDetailView(DetailView):
+ """
+ Display tournament detail.
+ """
+ model = Tournament
diff --git a/apps/registration/migrations/0001_initial.py b/apps/registration/migrations/0001_initial.py
index bae47af..d87bb4e 100644
--- a/apps/registration/migrations/0001_initial.py
+++ b/apps/registration/migrations/0001_initial.py
@@ -1,8 +1,11 @@
-# Generated by Django 3.1.4 on 2020-12-28 17:16
+# Generated by Django 3.0.11 on 2020-12-30 12:02
+import address.models
+import datetime
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
+import phonenumber_field.modelfields
import registration.models
@@ -11,9 +14,10 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('participation', '0001_initial'),
('contenttypes', '0002_remove_content_type_name'),
+ ('address', '0003_auto_20200830_1851'),
+ ('participation', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
@@ -23,7 +27,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('give_contact_to_animath', models.BooleanField(default=False, verbose_name='Grant Animath to contact me in the future about other actions')),
('email_confirmed', models.BooleanField(default=False, verbose_name='email confirmed')),
- ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_registration.registration_set+', to='contenttypes.contenttype')),
+ ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_registration.registration_set+', to='contenttypes.ContentType')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
],
options={
@@ -31,25 +35,16 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'registrations',
},
),
- migrations.CreateModel(
- name='AdminRegistration',
- fields=[
- ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')),
- ('role', models.TextField(verbose_name='role of the administrator')),
- ],
- options={
- 'verbose_name': 'admin registration',
- 'verbose_name_plural': 'admin registrations',
- },
- bases=('registration.registration',),
- ),
migrations.CreateModel(
name='ParticipantRegistration',
fields=[
- ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')),
+ ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.Registration')),
+ ('birth_date', models.DateField(default=datetime.date.today, verbose_name='birth date')),
+ ('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='phone number')),
('photo_authorization', models.FileField(blank=True, default='', upload_to=registration.models.get_random_photo_filename, verbose_name='photo authorization')),
('health_sheet', models.FileField(blank=True, default='', upload_to=registration.models.get_random_health_filename, verbose_name='health sheet')),
- ('team', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='participants', to='participation.team', verbose_name='team')),
+ ('address', address.models.AddressField(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.Address', verbose_name='address')),
+ ('team', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='participants', to='participation.Team', verbose_name='team')),
],
options={
'abstract': False,
@@ -60,7 +55,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='VolunteerRegistration',
fields=[
- ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')),
+ ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.Registration')),
('professional_activity', models.TextField(verbose_name='professional activity')),
],
options={
@@ -69,10 +64,22 @@ class Migration(migrations.Migration):
},
bases=('registration.registration',),
),
+ migrations.CreateModel(
+ name='AdminRegistration',
+ fields=[
+ ('volunteerregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.VolunteerRegistration')),
+ ('role', models.TextField(verbose_name='role of the administrator')),
+ ],
+ options={
+ 'verbose_name': 'admin registration',
+ 'verbose_name_plural': 'admin registrations',
+ },
+ bases=('registration.volunteerregistration',),
+ ),
migrations.CreateModel(
name='CoachRegistration',
fields=[
- ('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.participantregistration')),
+ ('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.ParticipantRegistration')),
('professional_activity', models.TextField(verbose_name='professional activity')),
],
options={
@@ -84,9 +91,12 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='StudentRegistration',
fields=[
- ('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.participantregistration')),
+ ('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.ParticipantRegistration')),
('student_class', models.IntegerField(choices=[(12, '12th grade'), (11, '11th grade'), (10, '10th grade or lower')], verbose_name='student class')),
('school', models.CharField(max_length=255, verbose_name='school')),
+ ('responsible_name', models.CharField(default='', max_length=255, verbose_name='responsible name')),
+ ('responsible_phone', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='responsible phone number')),
+ ('responsible_email', models.EmailField(default='', max_length=254, verbose_name='responsible email address')),
('parental_authorization', models.FileField(blank=True, default='', upload_to=registration.models.get_random_parental_filename, verbose_name='parental authorization')),
],
options={
diff --git a/apps/registration/migrations/0002_auto_20201228_2219.py b/apps/registration/migrations/0002_auto_20201228_2219.py
deleted file mode 100644
index 95e1b8c..0000000
--- a/apps/registration/migrations/0002_auto_20201228_2219.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# Generated by Django 3.0.11 on 2020-12-28 21:19
-
-import address.models
-from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
-import phonenumber_field.modelfields
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('address', '0003_auto_20200830_1851'),
- ('registration', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='participantregistration',
- name='address',
- field=address.models.AddressField(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.Address', verbose_name='address'),
- ),
- migrations.AddField(
- model_name='participantregistration',
- name='birth_date',
- field=models.DateField(default=django.utils.timezone.now, verbose_name='birth date'),
- ),
- migrations.AddField(
- model_name='participantregistration',
- name='phone_number',
- field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='phone number'),
- ),
- migrations.AddField(
- model_name='studentregistration',
- name='responsible_email',
- field=models.EmailField(default='', max_length=254, verbose_name='responsible email address'),
- ),
- migrations.AddField(
- model_name='studentregistration',
- name='responsible_name',
- field=models.CharField(default='', max_length=255, verbose_name='responsible name'),
- ),
- migrations.AddField(
- model_name='studentregistration',
- name='responsible_phone',
- field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='responsible phone number'),
- ),
- ]
diff --git a/apps/registration/models.py b/apps/registration/models.py
index ff1cdc4..532538e 100644
--- a/apps/registration/models.py
+++ b/apps/registration/models.py
@@ -259,7 +259,7 @@ class VolunteerRegistration(Registration):
return VolunteerRegistrationForm
-class AdminRegistration(Registration):
+class AdminRegistration(VolunteerRegistration):
"""
Specific registration for admins.
They have a field to justify they status.
diff --git a/tfjm/settings.py b/tfjm/settings.py
index 75f98ca..bfa8bd5 100644
--- a/tfjm/settings.py
+++ b/tfjm/settings.py
@@ -233,3 +233,6 @@ PHONENUMBER_DB_FORMAT = 'NATIONAL'
PHONENUMBER_DEFAULT_REGION = 'FR'
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
+
+# Use local Jquery
+JQUERY_URL = False
diff --git a/tfjm/templates/base.html b/tfjm/templates/base.html
index b233191..f2b23a0 100644
--- a/tfjm/templates/base.html
+++ b/tfjm/templates/base.html
@@ -19,23 +19,15 @@
{% endif %}
{# Bootstrap CSS #}
-
+
{# JQuery, Bootstrap and Turbolinks JavaScript #}
-
-
-
+
+