mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2024-12-24 17:42:23 +00:00
Login is possible
This commit is contained in:
parent
93735da1a4
commit
eead385218
39
apps/member/forms.py
Normal file
39
apps/member/forms.py
Normal file
@ -0,0 +1,39 @@
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from member.models import TFJMUser
|
||||
|
||||
|
||||
class SignUpForm(UserCreationForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["first_name"].required = True
|
||||
self.fields["last_name"].required = True
|
||||
print(self.fields["role"].choices)
|
||||
self.fields["role"].choices = [
|
||||
('', _("Choose a role...")),
|
||||
('participant', _("Participant")),
|
||||
('encadrant', _("Encadrant")),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
model = TFJMUser
|
||||
fields = (
|
||||
'role',
|
||||
'email',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'birth_date',
|
||||
'gender',
|
||||
'address',
|
||||
'postal_code',
|
||||
'city',
|
||||
'country',
|
||||
'phone_number',
|
||||
'school',
|
||||
'student_class',
|
||||
'responsible_name',
|
||||
'responsible_phone',
|
||||
'responsible_email',
|
||||
'description',
|
||||
)
|
@ -1,3 +1,6 @@
|
||||
import os
|
||||
from datetime import date
|
||||
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@ -38,7 +41,7 @@ class TFJMUser(AbstractUser):
|
||||
("female", _("Female")),
|
||||
("non-binary", _("Non binary")),
|
||||
],
|
||||
verbose_name=_("address"),
|
||||
verbose_name=_("gender"),
|
||||
)
|
||||
|
||||
address = models.CharField(
|
||||
@ -132,6 +135,7 @@ class TFJMUser(AbstractUser):
|
||||
)
|
||||
|
||||
year = models.PositiveIntegerField(
|
||||
default=os.getenv("TFJM_YEAR", date.today().year),
|
||||
verbose_name=_("year"),
|
||||
)
|
||||
|
||||
|
10
apps/member/urls.py
Normal file
10
apps/member/urls.py
Normal file
@ -0,0 +1,10 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import CreateUserView
|
||||
|
||||
|
||||
app_name = "member"
|
||||
|
||||
urlpatterns = [
|
||||
path('signup/', CreateUserView.as_view(), name="signup"),
|
||||
]
|
@ -1,3 +1,10 @@
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import CreateView
|
||||
|
||||
# Create your views here.
|
||||
from .forms import SignUpForm
|
||||
from .models import TFJMUser
|
||||
|
||||
|
||||
class CreateUserView(CreateView):
|
||||
model = TFJMUser
|
||||
form_class = SignUpForm
|
||||
template_name = "registration/signup.html"
|
||||
|
@ -1,4 +1,5 @@
|
||||
import os
|
||||
from datetime import date
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@ -58,7 +59,8 @@ class Tournament(models.Model):
|
||||
)
|
||||
|
||||
year = models.PositiveIntegerField(
|
||||
verbose_name=_("year")
|
||||
default=os.getenv("TFJM_YEAR", date.today().year),
|
||||
verbose_name=_("year"),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@ -117,6 +119,7 @@ class Team(models.Model):
|
||||
)
|
||||
|
||||
year = models.PositiveIntegerField(
|
||||
default=os.getenv("TFJM_YEAR", date.today().year),
|
||||
verbose_name=_("year"),
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TFJM2\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-04-29 04:43+0000\n"
|
||||
"POT-Creation-Date: 2020-04-29 06:24+0000\n"
|
||||
"PO-Revision-Date: 2020-04-29 02:30+0000\n"
|
||||
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
|
||||
"Language-Team: fr <LL@li.org>\n"
|
||||
@ -22,328 +22,514 @@ msgstr ""
|
||||
msgid "member"
|
||||
msgstr "membre"
|
||||
|
||||
#: apps/member/models.py:15
|
||||
#: apps/member/forms.py:14
|
||||
msgid "Choose a role..."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/forms.py:15
|
||||
msgid "Participant"
|
||||
msgstr "Participant"
|
||||
|
||||
#: apps/member/forms.py:16
|
||||
msgid "Encadrant"
|
||||
msgstr "Encadrant"
|
||||
|
||||
#: apps/member/models.py:18
|
||||
msgid "email"
|
||||
msgstr "Adresse électronique"
|
||||
|
||||
#: apps/member/models.py:23 apps/member/models.py:196 apps/member/models.py:209
|
||||
#: apps/member/models.py:230 apps/tournament/models.py:132
|
||||
#: apps/tournament/models.py:152
|
||||
#: apps/member/models.py:26 apps/member/models.py:214 apps/member/models.py:230
|
||||
#: apps/member/models.py:255 apps/tournament/models.py:147
|
||||
#: apps/tournament/models.py:167
|
||||
msgid "team"
|
||||
msgstr "équipe"
|
||||
|
||||
#: apps/member/models.py:29
|
||||
#: apps/member/models.py:32
|
||||
msgid "birth date"
|
||||
msgstr "date de naissance"
|
||||
|
||||
#: apps/member/models.py:37
|
||||
#: apps/member/models.py:40
|
||||
msgid "Male"
|
||||
msgstr "Homme"
|
||||
|
||||
#: apps/member/models.py:38
|
||||
#: apps/member/models.py:41
|
||||
msgid "Female"
|
||||
msgstr "Femme"
|
||||
|
||||
#: apps/member/models.py:39
|
||||
#: apps/member/models.py:42
|
||||
msgid "Non binary"
|
||||
msgstr "Non binaire"
|
||||
|
||||
#: apps/member/models.py:41 apps/member/models.py:48
|
||||
#: apps/member/models.py:44
|
||||
msgid "gender"
|
||||
msgstr "genre"
|
||||
|
||||
#: apps/member/models.py:51
|
||||
msgid "address"
|
||||
msgstr "adresse"
|
||||
|
||||
#: apps/member/models.py:54
|
||||
#: apps/member/models.py:57
|
||||
msgid "postal code"
|
||||
msgstr "code postal"
|
||||
|
||||
#: apps/member/models.py:61
|
||||
#: apps/member/models.py:64
|
||||
msgid "city"
|
||||
msgstr "ville"
|
||||
|
||||
#: apps/member/models.py:68
|
||||
#: apps/member/models.py:71
|
||||
msgid "country"
|
||||
msgstr "pays"
|
||||
|
||||
#: apps/member/models.py:76
|
||||
#: apps/member/models.py:79
|
||||
msgid "phone number"
|
||||
msgstr "numéro de téléphone"
|
||||
|
||||
#: apps/member/models.py:83
|
||||
#: apps/member/models.py:86
|
||||
msgid "school"
|
||||
msgstr "école"
|
||||
|
||||
#: apps/member/models.py:89
|
||||
#: apps/member/models.py:92
|
||||
msgid "Seconde or less"
|
||||
msgstr "Seconde ou inférieur"
|
||||
|
||||
#: apps/member/models.py:90
|
||||
#: apps/member/models.py:93
|
||||
msgid "Première"
|
||||
msgstr "Première"
|
||||
|
||||
#: apps/member/models.py:91
|
||||
#: apps/member/models.py:94
|
||||
msgid "Terminale"
|
||||
msgstr "Terminale"
|
||||
|
||||
#: apps/member/models.py:102
|
||||
#: apps/member/models.py:105
|
||||
msgid "responsible name"
|
||||
msgstr "nom du responsable"
|
||||
|
||||
#: apps/member/models.py:109
|
||||
#: apps/member/models.py:112
|
||||
msgid "responsible phone"
|
||||
msgstr "téléphone du responsable"
|
||||
|
||||
#: apps/member/models.py:115
|
||||
#: apps/member/models.py:118
|
||||
msgid "responsible email"
|
||||
msgstr "email du responsable"
|
||||
|
||||
#: apps/member/models.py:121 apps/tournament/models.py:33
|
||||
#: apps/member/models.py:124 apps/tournament/models.py:34
|
||||
msgid "description"
|
||||
msgstr "description"
|
||||
|
||||
#: apps/member/models.py:127
|
||||
#: apps/member/models.py:130
|
||||
msgid "admin"
|
||||
msgstr "administrateur"
|
||||
|
||||
#: apps/member/models.py:128
|
||||
#: apps/member/models.py:131
|
||||
msgid "organizer"
|
||||
msgstr "oragnisateur"
|
||||
|
||||
#: apps/member/models.py:129
|
||||
#: apps/member/models.py:132
|
||||
msgid "encadrant"
|
||||
msgstr "encadrant"
|
||||
|
||||
#: apps/member/models.py:130
|
||||
#: apps/member/models.py:133
|
||||
msgid "participant"
|
||||
msgstr "participant"
|
||||
|
||||
#: apps/member/models.py:135 apps/tournament/models.py:61
|
||||
#: apps/tournament/models.py:120
|
||||
#: apps/member/models.py:139 apps/tournament/models.py:63
|
||||
#: apps/tournament/models.py:123
|
||||
msgid "year"
|
||||
msgstr "année"
|
||||
|
||||
#: apps/member/models.py:139 apps/member/models.py:172
|
||||
#: apps/tournament/models.py:145
|
||||
#: apps/member/models.py:155 apps/member/models.py:187
|
||||
#: apps/tournament/models.py:160
|
||||
msgid "user"
|
||||
msgstr "utilisateur"
|
||||
|
||||
#: apps/member/models.py:140
|
||||
#: apps/member/models.py:156
|
||||
msgid "users"
|
||||
msgstr "utilisateurs"
|
||||
|
||||
#: apps/member/models.py:154
|
||||
#: apps/member/models.py:169
|
||||
msgid "file"
|
||||
msgstr "fichier"
|
||||
|
||||
#: apps/member/models.py:159
|
||||
#: apps/member/models.py:174
|
||||
msgid "uploaded at"
|
||||
msgstr "téléversé le"
|
||||
|
||||
#: apps/member/models.py:163
|
||||
#: apps/member/models.py:178
|
||||
msgid "document"
|
||||
msgstr "document"
|
||||
|
||||
#: apps/member/models.py:164
|
||||
#: apps/member/models.py:179
|
||||
msgid "documents"
|
||||
msgstr "documents"
|
||||
|
||||
#: apps/member/models.py:178
|
||||
#: apps/member/models.py:193
|
||||
msgid "Parental consent"
|
||||
msgstr "Autorisation parentale"
|
||||
|
||||
#: apps/member/models.py:179
|
||||
#: apps/member/models.py:194
|
||||
msgid "Photo consent"
|
||||
msgstr "Autorisation de droit à l'image"
|
||||
|
||||
#: apps/member/models.py:180
|
||||
#: apps/member/models.py:195
|
||||
msgid "Sanitary plug"
|
||||
msgstr "Fiche sanitaire"
|
||||
|
||||
#: apps/member/models.py:181 apps/tournament/models.py:163
|
||||
#: apps/member/models.py:196 apps/tournament/models.py:178
|
||||
msgid "Scholarship"
|
||||
msgstr "Bourse"
|
||||
|
||||
#: apps/member/models.py:183
|
||||
#: apps/member/models.py:198
|
||||
msgid "type"
|
||||
msgstr "type"
|
||||
|
||||
#: apps/member/models.py:187
|
||||
#: apps/member/models.py:202
|
||||
msgid "authorization"
|
||||
msgstr "autorisation"
|
||||
|
||||
#: apps/member/models.py:188
|
||||
#: apps/member/models.py:203
|
||||
msgid "authorizations"
|
||||
msgstr "autorisations"
|
||||
|
||||
#: apps/member/models.py:200
|
||||
msgid "{authorization} for user {user}"
|
||||
msgstr "{authorization} pour l'utilisateur {user}"
|
||||
|
||||
#: apps/member/models.py:218
|
||||
msgid "motivation letter"
|
||||
msgstr "lettre de motivation"
|
||||
|
||||
#: apps/member/models.py:201
|
||||
#: apps/member/models.py:219
|
||||
msgid "motivation letters"
|
||||
msgstr "lettres de motivation"
|
||||
|
||||
#: apps/member/models.py:213
|
||||
#: apps/member/models.py:222
|
||||
#, python-brace-format
|
||||
msgid "Motivation letter of team {team} ({trigram})"
|
||||
msgstr "Lettre de motivation de l'équipe {team} ({trigram})"
|
||||
|
||||
#: apps/member/models.py:234
|
||||
msgid "problem"
|
||||
msgstr "problème"
|
||||
|
||||
#: apps/member/models.py:221
|
||||
#: apps/member/models.py:242
|
||||
msgid "solution"
|
||||
msgstr "solution"
|
||||
|
||||
#: apps/member/models.py:222
|
||||
#: apps/member/models.py:243
|
||||
msgid "solutions"
|
||||
msgstr "solutions"
|
||||
|
||||
#: apps/member/models.py:236
|
||||
#: apps/member/models.py:246
|
||||
#, python-brace-format
|
||||
msgid "Solution of team {trigram} for problem {problem}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:261
|
||||
msgid "Defender"
|
||||
msgstr "Défenseur"
|
||||
|
||||
#: apps/member/models.py:237
|
||||
#: apps/member/models.py:262
|
||||
msgid "Opponent"
|
||||
msgstr "Opposant"
|
||||
|
||||
#: apps/member/models.py:238
|
||||
#: apps/member/models.py:263
|
||||
msgid "Rapporteur"
|
||||
msgstr "Rapporteur"
|
||||
|
||||
#: apps/member/models.py:240
|
||||
#: apps/member/models.py:265
|
||||
msgid "dest"
|
||||
msgstr "destinataire"
|
||||
|
||||
#: apps/member/models.py:248
|
||||
#: apps/member/models.py:273
|
||||
msgid "synthesis"
|
||||
msgstr "synthèse"
|
||||
|
||||
#: apps/member/models.py:249
|
||||
#: apps/member/models.py:274
|
||||
msgid "syntheses"
|
||||
msgstr "synthèses"
|
||||
|
||||
#: apps/tournament/apps.py:7 apps/tournament/models.py:69
|
||||
#: apps/tournament/models.py:90
|
||||
#: apps/member/models.py:277
|
||||
#, python-brace-format
|
||||
msgid "Synthesis of team {trigram} that is {dest} for problem {problem}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:285
|
||||
msgid "key"
|
||||
msgstr "clé"
|
||||
|
||||
#: apps/member/models.py:290
|
||||
msgid "value"
|
||||
msgstr "valeur"
|
||||
|
||||
#: apps/member/models.py:294
|
||||
msgid "configuration"
|
||||
msgstr "configuration"
|
||||
|
||||
#: apps/member/models.py:295
|
||||
msgid "configurations"
|
||||
msgstr "configurations"
|
||||
|
||||
#: apps/tournament/apps.py:7 apps/tournament/models.py:71
|
||||
#: apps/tournament/models.py:92
|
||||
msgid "tournament"
|
||||
msgstr "tournoi"
|
||||
|
||||
#: apps/tournament/models.py:10 apps/tournament/models.py:79
|
||||
#: apps/tournament/models.py:11 apps/tournament/models.py:81
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
#: apps/tournament/models.py:16
|
||||
#: apps/tournament/models.py:17
|
||||
msgid "organizers"
|
||||
msgstr "organisateurs"
|
||||
|
||||
#: apps/tournament/models.py:20
|
||||
#: apps/tournament/models.py:21
|
||||
msgid "size"
|
||||
msgstr "taille"
|
||||
|
||||
#: apps/tournament/models.py:25
|
||||
#: apps/tournament/models.py:26
|
||||
msgid "place"
|
||||
msgstr "lieu"
|
||||
|
||||
#: apps/tournament/models.py:29
|
||||
#: apps/tournament/models.py:30
|
||||
msgid "price"
|
||||
msgstr "prix"
|
||||
|
||||
#: apps/tournament/models.py:37 apps/tournament/models.py:41
|
||||
#: apps/tournament/models.py:38 apps/tournament/models.py:42
|
||||
msgid "date start"
|
||||
msgstr "date de début"
|
||||
|
||||
#: apps/tournament/models.py:45
|
||||
#: apps/tournament/models.py:46
|
||||
msgid "date of registration closing"
|
||||
msgstr "date de clôture des inscriptions"
|
||||
|
||||
#: apps/tournament/models.py:49
|
||||
#: apps/tournament/models.py:50
|
||||
msgid "date of maximal solution submission"
|
||||
msgstr "date d'envoi maximal des solutions"
|
||||
|
||||
#: apps/tournament/models.py:53
|
||||
#: apps/tournament/models.py:54
|
||||
msgid "date of maximal syntheses submission"
|
||||
msgstr "date d'envoi maximal des notes de synthèses"
|
||||
|
||||
#: apps/tournament/models.py:57
|
||||
#: apps/tournament/models.py:58
|
||||
msgid "final tournament"
|
||||
msgstr "finale"
|
||||
|
||||
#: apps/tournament/models.py:70
|
||||
#: apps/tournament/models.py:72
|
||||
msgid "tournaments"
|
||||
msgstr "tournois"
|
||||
|
||||
#: apps/tournament/models.py:84
|
||||
#: apps/tournament/models.py:86
|
||||
msgid "trigram"
|
||||
msgstr "trigramme"
|
||||
|
||||
#: apps/tournament/models.py:95
|
||||
#: apps/tournament/models.py:97
|
||||
msgid "inscription date"
|
||||
msgstr "date d'inscription"
|
||||
|
||||
#: apps/tournament/models.py:101 apps/tournament/models.py:172
|
||||
#: apps/tournament/models.py:103 apps/tournament/models.py:187
|
||||
msgid "Registration not validated"
|
||||
msgstr "Inscription non validée"
|
||||
|
||||
#: apps/tournament/models.py:102 apps/tournament/models.py:173
|
||||
#: apps/tournament/models.py:104 apps/tournament/models.py:188
|
||||
msgid "Waiting for validation"
|
||||
msgstr "En attente de validation"
|
||||
|
||||
#: apps/tournament/models.py:103 apps/tournament/models.py:174
|
||||
#: apps/tournament/models.py:105 apps/tournament/models.py:189
|
||||
msgid "Registration validated"
|
||||
msgstr "Inscription validée"
|
||||
|
||||
#: apps/tournament/models.py:105 apps/tournament/models.py:176
|
||||
#: apps/tournament/models.py:107 apps/tournament/models.py:191
|
||||
msgid "validation status"
|
||||
msgstr "statut de validation"
|
||||
|
||||
#: apps/tournament/models.py:110
|
||||
#: apps/tournament/models.py:112
|
||||
msgid "selected for final"
|
||||
msgstr "sélectionnée pour la finale"
|
||||
|
||||
#: apps/tournament/models.py:116
|
||||
#: apps/tournament/models.py:118
|
||||
msgid "access code"
|
||||
msgstr "code d'accès"
|
||||
|
||||
#: apps/tournament/models.py:133
|
||||
#: apps/tournament/models.py:148
|
||||
msgid "teams"
|
||||
msgstr "équipes"
|
||||
|
||||
#: apps/tournament/models.py:158
|
||||
#: apps/tournament/models.py:173
|
||||
msgid "Not paid"
|
||||
msgstr "Non payé"
|
||||
|
||||
#: apps/tournament/models.py:159
|
||||
#: apps/tournament/models.py:174
|
||||
msgid "Credit card"
|
||||
msgstr "Carte bancaire"
|
||||
|
||||
#: apps/tournament/models.py:160
|
||||
#: apps/tournament/models.py:175
|
||||
msgid "Bank check"
|
||||
msgstr "Chèque bancaire"
|
||||
|
||||
#: apps/tournament/models.py:161
|
||||
#: apps/tournament/models.py:176
|
||||
msgid "Bank transfer"
|
||||
msgstr "Virement bancaire"
|
||||
|
||||
#: apps/tournament/models.py:162
|
||||
#: apps/tournament/models.py:177
|
||||
msgid "Cash"
|
||||
msgstr "Espèces"
|
||||
|
||||
#: apps/tournament/models.py:166
|
||||
#: apps/tournament/models.py:181
|
||||
msgid "payment method"
|
||||
msgstr "moyen de paiement"
|
||||
|
||||
#: apps/tournament/models.py:180
|
||||
#: apps/tournament/models.py:195
|
||||
msgid "payment"
|
||||
msgstr "paiement"
|
||||
|
||||
#: apps/tournament/models.py:181
|
||||
#: apps/tournament/models.py:196
|
||||
msgid "payments"
|
||||
msgstr "paiements"
|
||||
|
||||
#: apps/tournament/models.py:184
|
||||
#: apps/tournament/models.py:199
|
||||
#, python-brace-format
|
||||
msgid "Payment of {user}"
|
||||
msgstr "Paiement de {user}"
|
||||
|
||||
#: tfjm/settings.py:128
|
||||
#: templates/base.html:11
|
||||
msgid "The inscription site of the TFJM²."
|
||||
msgstr "Le site d'inscription au TFJM²."
|
||||
|
||||
#: templates/registration/email_validation_complete.html:6
|
||||
msgid "Your email have successfully been validated."
|
||||
msgstr "Votre adresse e-mail a bien été validée."
|
||||
|
||||
#: templates/registration/email_validation_complete.html:8
|
||||
#, python-format
|
||||
msgid "You can now <a href=\"%(login_url)s\">log in</a>."
|
||||
msgstr "Vous pouvez désormais <a href=\"%(login_url)s\">vous connecter</a>"
|
||||
|
||||
#: templates/registration/email_validation_complete.html:13
|
||||
msgid ""
|
||||
"The link was invalid. The token may have expired. Please send us an email to "
|
||||
"activate your account."
|
||||
msgstr ""
|
||||
"Le lien est invalide. Le jeton a du expirer. Merci de nous envoyer un mail "
|
||||
"afin d'activer votre compte."
|
||||
|
||||
#: templates/registration/logged_out.html:8
|
||||
msgid "Thanks for spending some quality time with the Web site today."
|
||||
msgstr "Merci d'avoir utilisé la plateforme du TFJM²."
|
||||
|
||||
#: templates/registration/logged_out.html:9
|
||||
msgid "Log in again"
|
||||
msgstr "Se connecter à nouveau"
|
||||
|
||||
#: templates/registration/login.html:7 templates/registration/login.html:8
|
||||
#: templates/registration/login.html:22
|
||||
#: templates/registration/password_reset_complete.html:10
|
||||
msgid "Log in"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: templates/registration/login.html:13
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You are authenticated as %(user)s, but are not authorized to access this "
|
||||
"page. Would you like to login to a different account?"
|
||||
msgstr ""
|
||||
"Vous êtes déjà connecté sous le nom %(user)s, mais vous n'êtes pas autorisés "
|
||||
"à accéder à cette page. Souhaitez-vous vous connecter sous un compte différent ?"
|
||||
|
||||
#: templates/registration/login.html:23
|
||||
msgid "Forgotten your password or username?"
|
||||
msgstr "Mot de passe oublié ?"
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:3
|
||||
msgid "Hi"
|
||||
msgstr "Bonjour"
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:5
|
||||
msgid ""
|
||||
"You recently registered on the Note Kfet. Please click on the link below to "
|
||||
"confirm your registration."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:9
|
||||
msgid ""
|
||||
"This link is only valid for a couple of days, after that you will need to "
|
||||
"contact us to validate your email."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:11
|
||||
msgid ""
|
||||
"After that, you'll have to wait that someone validates your account before "
|
||||
"you can log in. You will need to pay your membership in the Kfet."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:13
|
||||
msgid "Thanks"
|
||||
msgstr "Merci"
|
||||
|
||||
#: templates/registration/mails/email_validation_email.html:15
|
||||
msgid "The Note Kfet team."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_change_done.html:8
|
||||
msgid "Your password was changed."
|
||||
msgstr "Votre mot de passe a été changé"
|
||||
|
||||
#: templates/registration/password_change_form.html:9
|
||||
msgid ""
|
||||
"Please enter your old password, for security's sake, and then enter your new "
|
||||
"password twice so we can verify you typed it in correctly."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_change_form.html:11
|
||||
#: templates/registration/password_reset_confirm.html:12
|
||||
msgid "Change my password"
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_complete.html:8
|
||||
msgid "Your password has been set. You may go ahead and log in now."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_confirm.html:9
|
||||
msgid ""
|
||||
"Please enter your new password twice so we can verify you typed it in "
|
||||
"correctly."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_confirm.html:15
|
||||
msgid ""
|
||||
"The password reset link was invalid, possibly because it has already been "
|
||||
"used. Please request a new password reset."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_done.html:8
|
||||
msgid ""
|
||||
"We've emailed you instructions for setting your password, if an account "
|
||||
"exists with the email you entered. You should receive them shortly."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_done.html:9
|
||||
msgid ""
|
||||
"If you don't receive an email, please make sure you've entered the address "
|
||||
"you registered with, and check your spam folder."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_form.html:8
|
||||
msgid ""
|
||||
"Forgotten your password? Enter your email address below, and we'll email "
|
||||
"instructions for setting a new one."
|
||||
msgstr ""
|
||||
|
||||
#: templates/registration/password_reset_form.html:11
|
||||
msgid "Reset my password"
|
||||
msgstr "Réinitialiser mon mot de passe"
|
||||
|
||||
#: templates/registration/signup.html:5 templates/registration/signup.html:8
|
||||
#: templates/registration/signup.html:14
|
||||
msgid "Sign up"
|
||||
msgstr "S'inscrire"
|
||||
|
||||
#: tfjm/settings.py:135
|
||||
msgid "English"
|
||||
msgstr "Anglais"
|
||||
|
||||
#: tfjm/settings.py:129
|
||||
#: tfjm/settings.py:136
|
||||
msgid "French"
|
||||
msgstr "Français"
|
||||
|
121
static/bootstrap_datepicker_plus/css/datepicker-widget.css
Normal file
121
static/bootstrap_datepicker_plus/css/datepicker-widget.css
Normal file
@ -0,0 +1,121 @@
|
||||
@font-face {
|
||||
font-family: 'Glyphicons Halflings';
|
||||
src: url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot');
|
||||
src: url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
|
||||
url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff2') format('woff2'),
|
||||
url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff') format('woff'),
|
||||
url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.ttf') format('truetype'),
|
||||
url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
|
||||
}
|
||||
|
||||
.glyphicon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
font-family: 'Glyphicons Halflings';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.glyphicon-time:before {
|
||||
content: "\e023";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-left:before {
|
||||
content: "\e079";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-right:before {
|
||||
content: "\e080";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-up:before {
|
||||
content: "\e113";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-down:before {
|
||||
content: "\e114";
|
||||
}
|
||||
|
||||
.glyphicon-calendar:before {
|
||||
content: "\e109";
|
||||
}
|
||||
|
||||
.glyphicon-screenshot:before {
|
||||
content: "\e087";
|
||||
}
|
||||
|
||||
.glyphicon-trash:before {
|
||||
content: "\e020";
|
||||
}
|
||||
|
||||
.glyphicon-remove:before {
|
||||
content: "\e014";
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget .btn {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 1.42857143;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
float: left;
|
||||
min-width: 160px;
|
||||
padding: 5px 0;
|
||||
margin: 2px 0 0;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
list-style: none;
|
||||
background-color: #fff;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, .15);
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget .list-unstyled {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget .collapse {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget .collapse.in {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* fix for bootstrap4 */
|
||||
.bootstrap-datetimepicker-widget .table-condensed > thead > tr > th,
|
||||
.bootstrap-datetimepicker-widget .table-condensed > tbody > tr > td,
|
||||
.bootstrap-datetimepicker-widget .table-condensed > tfoot > tr > td {
|
||||
padding: 5px;
|
||||
}
|
55
static/bootstrap_datepicker_plus/js/datepicker-widget.js
Normal file
55
static/bootstrap_datepicker_plus/js/datepicker-widget.js
Normal file
@ -0,0 +1,55 @@
|
||||
jQuery(function ($) {
|
||||
var datepickerDict = {};
|
||||
var isBootstrap4 = $.fn.collapse.Constructor.VERSION.split('.').shift() == "4";
|
||||
function fixMonthEndDate(e, picker) {
|
||||
e.date && picker.val().length && picker.val(e.date.endOf('month').format('YYYY-MM-DD'));
|
||||
}
|
||||
$("[dp_config]:not([disabled])").each(function (i, element) {
|
||||
var $element = $(element), data = {};
|
||||
try {
|
||||
data = JSON.parse($element.attr('dp_config'));
|
||||
}
|
||||
catch (x) { }
|
||||
if (data.id && data.options) {
|
||||
data.$element = $element.datetimepicker(data.options);
|
||||
data.datepickerdata = $element.data("DateTimePicker");
|
||||
datepickerDict[data.id] = data;
|
||||
data.$element.next('.input-group-addon').on('click', function(){
|
||||
data.datepickerdata.show();
|
||||
});
|
||||
if(isBootstrap4){
|
||||
data.$element.on("dp.show", function (e) {
|
||||
$('.collapse.in').addClass('show');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
$.each(datepickerDict, function (id, to_picker) {
|
||||
if (to_picker.linked_to) {
|
||||
var from_picker = datepickerDict[to_picker.linked_to];
|
||||
from_picker.datepickerdata.maxDate(to_picker.datepickerdata.date() || false);
|
||||
to_picker.datepickerdata.minDate(from_picker.datepickerdata.date() || false);
|
||||
from_picker.$element.on("dp.change", function (e) {
|
||||
to_picker.datepickerdata.minDate(e.date || false);
|
||||
});
|
||||
to_picker.$element.on("dp.change", function (e) {
|
||||
if (to_picker.picker_type == 'MONTH') fixMonthEndDate(e, to_picker.$element);
|
||||
from_picker.datepickerdata.maxDate(e.date || false);
|
||||
});
|
||||
if (to_picker.picker_type == 'MONTH') {
|
||||
to_picker.$element.on("dp.hide", function (e) {
|
||||
fixMonthEndDate(e, to_picker.$element);
|
||||
});
|
||||
fixMonthEndDate({ date: to_picker.datepickerdata.date() }, to_picker.$element);
|
||||
}
|
||||
}
|
||||
});
|
||||
if(isBootstrap4) {
|
||||
$('body').on('show.bs.collapse','.bootstrap-datetimepicker-widget .collapse',function(e){
|
||||
$(e.target).addClass('in');
|
||||
});
|
||||
$('body').on('hidden.bs.collapse','.bootstrap-datetimepicker-widget .collapse',function(e){
|
||||
$(e.target).removeClass('in');
|
||||
});
|
||||
}
|
||||
});
|
11
templates/amount_input.html
Normal file
11
templates/amount_input.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div class="input-group">
|
||||
<input class="form-control mx-auto d-block" type="number" min="0" step="0.01"
|
||||
{% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %}
|
||||
name="{{ widget.name }}"
|
||||
{% for name, value in widget.attrs.items %}
|
||||
{% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %}
|
||||
{% endfor %}>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">€</span>
|
||||
</div>
|
||||
</div>
|
9
templates/autocomplete_model.html
Normal file
9
templates/autocomplete_model.html
Normal file
@ -0,0 +1,9 @@
|
||||
<input type="hidden" name="{{ widget.name }}" {% if widget.attrs.model_pk %}value="{{ widget.attrs.model_pk }}"{% endif %} id="{{ widget.attrs.id }}_pk">
|
||||
<input type="text"
|
||||
{% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %}
|
||||
name="{{ widget.name }}_name" autocomplete="off"
|
||||
{% for name, value in widget.attrs.items %}
|
||||
{% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %}
|
||||
{% endfor %}>
|
||||
<ul class="list-group list-group-flush" id="{{ widget.attrs.id }}_list">
|
||||
</ul>
|
@ -155,7 +155,7 @@
|
||||
<a class="nav-link" href="{% url "login" %}"><i class="fas fa-sign-in-alt"></i> Connexion</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/inscription"><i class="fas fa-user-plus"></i> Inscription</a>
|
||||
<a class="nav-link" href="{% url "member:signup" %}"><i class="fas fa-user-plus"></i> Inscription</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item active">
|
||||
|
6
templates/bootstrap_datepicker_plus/date_picker.html
Normal file
6
templates/bootstrap_datepicker_plus/date_picker.html
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="input-group date">
|
||||
{% include "bootstrap_datepicker_plus/input.html" %}
|
||||
<div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
|
||||
<div class="input-group-text"><i class="glyphicon glyphicon-calendar"></i></div>
|
||||
</div>
|
||||
</div>
|
4
templates/bootstrap_datepicker_plus/input.html
Normal file
4
templates/bootstrap_datepicker_plus/input.html
Normal file
@ -0,0 +1,4 @@
|
||||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None and widget.value != "" %}
|
||||
value="{{ widget.value }}"{% endif %}{% for name, value in widget.attrs.items %}{% ifnotequal value False %}
|
||||
{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}
|
||||
{% endifnotequal %}{% endfor %}/>
|
6
templates/bootstrap_datepicker_plus/time_picker.html
Normal file
6
templates/bootstrap_datepicker_plus/time_picker.html
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="input-group date">
|
||||
{% include "bootstrap_datepicker_plus/input.html" %}
|
||||
<div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
|
||||
<div class="input-group-text"><i class="glyphicon glyphicon-time"></i></div>
|
||||
</div>
|
||||
</div>
|
8
templates/colorfield/color.html
Executable file
8
templates/colorfield/color.html
Executable file
@ -0,0 +1,8 @@
|
||||
<input type="text"
|
||||
id="{{ widget.attrs.id }}"
|
||||
class="form-control colorfield_field jscolor"
|
||||
name="{{ widget.name }}"
|
||||
value="{% firstof widget.value widget.attrs.default '' %}"
|
||||
placeholder="{% firstof widget.value widget.attrs.default '' %}"
|
||||
data-jscolor="{hash:true,width:225,height:150,required:{% if widget.attrs.required %}true{% else %}false{% endif %}}"
|
||||
{% if widget.attrs.required %}required{% endif %} />
|
15
templates/registration/mails/email_validation_email.html
Normal file
15
templates/registration/mails/email_validation_email.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% trans "Hi" %} {{ user.username }},
|
||||
|
||||
{% trans "You recently registered on the Note Kfet. Please click on the link below to confirm your registration." %}
|
||||
|
||||
https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %}
|
||||
|
||||
{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %}
|
||||
|
||||
{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %}
|
||||
|
||||
{% trans "Thanks" %},
|
||||
|
||||
{% trans "The Note Kfet team." %}
|
@ -1,20 +1,15 @@
|
||||
<!-- templates/signup.html -->
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Sign up" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{% trans "Sign up" %}</h2>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans %}If you already signed up, your registration is taken into account. The BDE must validate your account before your can log in. You have to go to the Kfet and pay the registration fee. You must also validate your email address by following the link you received.{% endblocktrans %}
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{{ profile_form|crispy }}
|
||||
<button class="btn btn-success" type="submit">
|
||||
{% trans "Sign up" %}
|
||||
</button>
|
||||
|
325
tfjm/inputs.py
Normal file
325
tfjm/inputs.py
Normal file
@ -0,0 +1,325 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from json import dumps as json_dumps
|
||||
|
||||
from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput, Widget
|
||||
|
||||
|
||||
class AmountInput(NumberInput):
|
||||
"""
|
||||
This input type lets the user type amounts in euros, but forms receive data in cents
|
||||
"""
|
||||
template_name = "amount_input.html"
|
||||
|
||||
def format_value(self, value):
|
||||
return None if value is None or value == "" else "{:.02f}".format(int(value) / 100, )
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
val = super().value_from_datadict(data, files, name)
|
||||
return str(int(100 * float(val))) if val else val
|
||||
|
||||
|
||||
class Autocomplete(TextInput):
|
||||
template_name = "autocomplete_model.html"
|
||||
|
||||
def __init__(self, model, attrs=None):
|
||||
super().__init__(attrs)
|
||||
|
||||
self.model = model
|
||||
self.model_pk = None
|
||||
|
||||
class Media:
|
||||
"""JS/CSS resources needed to render the date-picker calendar."""
|
||||
|
||||
js = ('js/autocomplete_model.js', )
|
||||
|
||||
def format_value(self, value):
|
||||
if value:
|
||||
self.attrs["model_pk"] = int(value)
|
||||
return str(self.model.objects.get(pk=int(value)))
|
||||
return ""
|
||||
|
||||
|
||||
class ColorWidget(Widget):
|
||||
"""
|
||||
Pulled from django-colorfield.
|
||||
Select a color.
|
||||
"""
|
||||
template_name = 'colorfield/color.html'
|
||||
|
||||
class Media:
|
||||
js = [
|
||||
'colorfield/jscolor/jscolor.min.js',
|
||||
'colorfield/colorfield.js',
|
||||
]
|
||||
|
||||
def format_value(self, value):
|
||||
if value is None:
|
||||
value = 0xFFFFFF
|
||||
return "#{:06X}".format(value)
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
val = super().value_from_datadict(data, files, name)
|
||||
return int(val[1:], 16)
|
||||
|
||||
|
||||
"""
|
||||
The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github:
|
||||
https://github.com/monim67/django-bootstrap-datepicker-plus
|
||||
This is distributed under Apache License 2.0.
|
||||
|
||||
This adds datetime pickers with bootstrap.
|
||||
"""
|
||||
|
||||
"""Contains Base Date-Picker input class for widgets of this package."""
|
||||
|
||||
|
||||
class DatePickerDictionary:
|
||||
"""Keeps track of all date-picker input classes."""
|
||||
|
||||
_i = 0
|
||||
items = dict()
|
||||
|
||||
@classmethod
|
||||
def generate_id(cls):
|
||||
"""Return a unique ID for each date-picker input class."""
|
||||
cls._i += 1
|
||||
return 'dp_%s' % cls._i
|
||||
|
||||
|
||||
class BasePickerInput(DateTimeBaseInput):
|
||||
"""Base Date-Picker input class for widgets of this package."""
|
||||
|
||||
template_name = 'bootstrap_datepicker_plus/date_picker.html'
|
||||
picker_type = 'DATE'
|
||||
format = '%Y-%m-%d'
|
||||
config = {}
|
||||
_default_config = {
|
||||
'id': None,
|
||||
'picker_type': None,
|
||||
'linked_to': None,
|
||||
'options': {} # final merged options
|
||||
}
|
||||
options = {} # options extended by user
|
||||
options_param = {} # options passed as parameter
|
||||
_default_options = {
|
||||
'showClose': True,
|
||||
'showClear': True,
|
||||
'showTodayButton': True,
|
||||
"locale": "fr",
|
||||
}
|
||||
|
||||
# source: https://github.com/tutorcruncher/django-bootstrap3-datetimepicker
|
||||
# file: /blob/31fbb09/bootstrap3_datetime/widgets.py#L33
|
||||
format_map = (
|
||||
('DDD', r'%j'),
|
||||
('DD', r'%d'),
|
||||
('MMMM', r'%B'),
|
||||
('MMM', r'%b'),
|
||||
('MM', r'%m'),
|
||||
('YYYY', r'%Y'),
|
||||
('YY', r'%y'),
|
||||
('HH', r'%H'),
|
||||
('hh', r'%I'),
|
||||
('mm', r'%M'),
|
||||
('ss', r'%S'),
|
||||
('a', r'%p'),
|
||||
('ZZ', r'%z'),
|
||||
)
|
||||
|
||||
class Media:
|
||||
"""JS/CSS resources needed to render the date-picker calendar."""
|
||||
|
||||
js = (
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/'
|
||||
'moment-with-locales.min.js',
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
|
||||
'4.17.47/js/bootstrap-datetimepicker.min.js',
|
||||
'bootstrap_datepicker_plus/js/datepicker-widget.js'
|
||||
)
|
||||
css = {'all': (
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
|
||||
'4.17.47/css/bootstrap-datetimepicker.css',
|
||||
'bootstrap_datepicker_plus/css/datepicker-widget.css'
|
||||
), }
|
||||
|
||||
@classmethod
|
||||
def format_py2js(cls, datetime_format):
|
||||
"""Convert python datetime format to moment datetime format."""
|
||||
for js_format, py_format in cls.format_map:
|
||||
datetime_format = datetime_format.replace(py_format, js_format)
|
||||
return datetime_format
|
||||
|
||||
@classmethod
|
||||
def format_js2py(cls, datetime_format):
|
||||
"""Convert moment datetime format to python datetime format."""
|
||||
for js_format, py_format in cls.format_map:
|
||||
datetime_format = datetime_format.replace(js_format, py_format)
|
||||
return datetime_format
|
||||
|
||||
def __init__(self, attrs=None, format=None, options=None):
|
||||
"""Initialize the Date-picker widget."""
|
||||
self.format_param = format
|
||||
self.options_param = options if options else {}
|
||||
self.config = self._default_config.copy()
|
||||
self.config['id'] = DatePickerDictionary.generate_id()
|
||||
self.config['picker_type'] = self.picker_type
|
||||
self.config['options'] = self._calculate_options()
|
||||
attrs = attrs if attrs else {}
|
||||
if 'class' not in attrs:
|
||||
attrs['class'] = 'form-control'
|
||||
super().__init__(attrs, self._calculate_format())
|
||||
|
||||
def _calculate_options(self):
|
||||
"""Calculate and Return the options."""
|
||||
_options = self._default_options.copy()
|
||||
_options.update(self.options)
|
||||
if self.options_param:
|
||||
_options.update(self.options_param)
|
||||
return _options
|
||||
|
||||
def _calculate_format(self):
|
||||
"""Calculate and Return the datetime format."""
|
||||
_format = self.format_param if self.format_param else self.format
|
||||
if self.config['options'].get('format'):
|
||||
_format = self.format_js2py(self.config['options'].get('format'))
|
||||
else:
|
||||
self.config['options']['format'] = self.format_py2js(_format)
|
||||
return _format
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
"""Return widget context dictionary."""
|
||||
context = super().get_context(
|
||||
name, value, attrs)
|
||||
context['widget']['attrs']['dp_config'] = json_dumps(self.config)
|
||||
return context
|
||||
|
||||
def start_of(self, event_id):
|
||||
"""
|
||||
Set Date-Picker as the start-date of a date-range.
|
||||
|
||||
Args:
|
||||
- event_id (string): User-defined unique id for linking two fields
|
||||
"""
|
||||
DatePickerDictionary.items[str(event_id)] = self
|
||||
return self
|
||||
|
||||
def end_of(self, event_id, import_options=True):
|
||||
"""
|
||||
Set Date-Picker as the end-date of a date-range.
|
||||
|
||||
Args:
|
||||
- event_id (string): User-defined unique id for linking two fields
|
||||
- import_options (bool): inherit options from start-date input,
|
||||
default: TRUE
|
||||
"""
|
||||
event_id = str(event_id)
|
||||
if event_id in DatePickerDictionary.items:
|
||||
linked_picker = DatePickerDictionary.items[event_id]
|
||||
self.config['linked_to'] = linked_picker.config['id']
|
||||
if import_options:
|
||||
backup_moment_format = self.config['options']['format']
|
||||
self.config['options'].update(linked_picker.config['options'])
|
||||
self.config['options'].update(self.options_param)
|
||||
if self.format_param or 'format' in self.options_param:
|
||||
self.config['options']['format'] = backup_moment_format
|
||||
else:
|
||||
self.format = linked_picker.format
|
||||
# Setting useCurrent is necessary, see following issue
|
||||
# https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075
|
||||
self.config['options']['useCurrent'] = False
|
||||
self._link_to(linked_picker)
|
||||
else:
|
||||
raise KeyError(
|
||||
'start-date not specified for event_id "%s"' % event_id)
|
||||
return self
|
||||
|
||||
def _link_to(self, linked_picker):
|
||||
"""
|
||||
Executed when two date-inputs are linked together.
|
||||
|
||||
This method for sub-classes to override to customize the linking.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class DatePickerInput(BasePickerInput):
|
||||
"""
|
||||
Widget to display a Date-Picker Calendar on a DateField property.
|
||||
|
||||
Args:
|
||||
- attrs (dict): HTML attributes of rendered HTML input
|
||||
- format (string): Python DateTime format eg. "%Y-%m-%d"
|
||||
- options (dict): Options to customize the widget, see README
|
||||
"""
|
||||
|
||||
picker_type = 'DATE'
|
||||
format = '%Y-%m-%d'
|
||||
format_key = 'DATE_INPUT_FORMATS'
|
||||
|
||||
|
||||
class TimePickerInput(BasePickerInput):
|
||||
"""
|
||||
Widget to display a Time-Picker Calendar on a TimeField property.
|
||||
|
||||
Args:
|
||||
- attrs (dict): HTML attributes of rendered HTML input
|
||||
- format (string): Python DateTime format eg. "%Y-%m-%d"
|
||||
- options (dict): Options to customize the widget, see README
|
||||
"""
|
||||
|
||||
picker_type = 'TIME'
|
||||
format = '%H:%M'
|
||||
format_key = 'TIME_INPUT_FORMATS'
|
||||
template_name = 'bootstrap_datepicker_plus/time_picker.html'
|
||||
|
||||
|
||||
class DateTimePickerInput(BasePickerInput):
|
||||
"""
|
||||
Widget to display a DateTime-Picker Calendar on a DateTimeField property.
|
||||
|
||||
Args:
|
||||
- attrs (dict): HTML attributes of rendered HTML input
|
||||
- format (string): Python DateTime format eg. "%Y-%m-%d"
|
||||
- options (dict): Options to customize the widget, see README
|
||||
"""
|
||||
|
||||
picker_type = 'DATETIME'
|
||||
format = '%Y-%m-%d %H:%M'
|
||||
format_key = 'DATETIME_INPUT_FORMATS'
|
||||
|
||||
|
||||
class MonthPickerInput(BasePickerInput):
|
||||
"""
|
||||
Widget to display a Month-Picker Calendar on a DateField property.
|
||||
|
||||
Args:
|
||||
- attrs (dict): HTML attributes of rendered HTML input
|
||||
- format (string): Python DateTime format eg. "%Y-%m-%d"
|
||||
- options (dict): Options to customize the widget, see README
|
||||
"""
|
||||
|
||||
picker_type = 'MONTH'
|
||||
format = '01/%m/%Y'
|
||||
format_key = 'DATE_INPUT_FORMATS'
|
||||
|
||||
|
||||
class YearPickerInput(BasePickerInput):
|
||||
"""
|
||||
Widget to display a Year-Picker Calendar on a DateField property.
|
||||
|
||||
Args:
|
||||
- attrs (dict): HTML attributes of rendered HTML input
|
||||
- format (string): Python DateTime format eg. "%Y-%m-%d"
|
||||
- options (dict): Options to customize the widget, see README
|
||||
"""
|
||||
|
||||
picker_type = 'YEAR'
|
||||
format = '01/01/%Y'
|
||||
format_key = 'DATE_INPUT_FORMATS'
|
||||
|
||||
def _link_to(self, linked_picker):
|
||||
"""Customize the options when linked with other date-time input"""
|
||||
yformat = self.config['options']['format'].replace('-01-01', '-12-31')
|
||||
self.config['options']['format'] = yformat
|
@ -25,6 +25,9 @@ urlpatterns = [
|
||||
path('admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
path('admin/', admin.site.urls, name="admin"),
|
||||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
|
||||
path('member/', include('member.urls')),
|
||||
path('tournament/', include('tournament.urls')),
|
||||
]
|
||||
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
Loading…
Reference in New Issue
Block a user