Compare commits

...

17 Commits

Author SHA1 Message Date
bleizi 8f663f2451 Merge branch 'migration-django-4-2' into 'main'
[Draft] nk20 v2.0.0 with django 4.2

See merge request bde/nk20!230
2024-03-30 20:58:46 +01:00
quark 7f182ee2ee Merge branch 'traduction_inclusive_fr' into 'main'
Réécriture en inclusif de l'ensemble des textes français de la note

See merge request bde/nk20!246
2024-03-30 13:24:06 +01:00
quark 3132aa4c38 Prise en compte des commentaires de Korenstin 2024-03-30 12:44:51 +01:00
quark c7eb774859 Prise en compte des commentaires 2024-03-30 11:20:23 +01:00
quark 32f8d285b3 Prise en compte des commentaires 2024-03-30 11:12:33 +01:00
quark 050256ea13 Réécriture en inclusif de l'ensemble des textes français de la note 2024-03-29 17:59:43 +01:00
bleizi b7a71d911d _get_validtion_exclusions() now return a set, PIL.Image.ANTIALIAS was renamed LANCZOS and typo in .gitlab-ci.yml 2024-02-12 22:56:43 +01:00
bleizi 2ee7f41dfe tests with ubuntu 22.04, django-bootstrap-datepicker-plus is a standalone package and fix encoding in tests 2024-02-12 21:25:07 +01:00
bleizi fb3337966e
bootstrap4 is now a standalone package from crispy-forms 2024-02-11 22:24:37 +01:00
bleizi 399a32bece
default auto field 2024-02-11 16:51:48 +01:00
bleizi 82fea65b5e
django_htcpcp_tea in middleware only if in apps 2024-02-07 20:03:57 +01:00
bleizi abc88d0118
replace url from django.conf.urls by re_path from django.urls 2024-02-07 18:21:08 +01:00
bleizi b6b81a8b8f
typo 2024-02-07 18:05:32 +01:00
bleizi d228dbf225
fix some breaking changes and linters 2024-02-07 18:02:56 +01:00
bleizi 516a7f4be5
Remove importation of django-htcpcp-tea which is not compatible with django 4.2 2024-01-24 20:14:32 +01:00
bleizi 2f8c9b54e7
Remove importation of django-cas-server which is not compatible with django 4.2 2024-01-24 19:58:55 +01:00
bleizi e9f18c3ed9
migrate to django 4.2 (LTS), change requirement and tests. remove depreciated ifnotequal 2024-01-24 19:18:02 +01:00
22 changed files with 208 additions and 447 deletions

View File

@ -7,40 +7,8 @@ stages:
variables:
GIT_SUBMODULE_STRATEGY: recursive
# Debian Buster
py37-django22:
stage: test
image: debian:buster-backports
before_script:
- >
apt-get update &&
apt-get install --no-install-recommends -t buster-backports -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py37-django22
# Ubuntu 20.04
py38-django22:
stage: test
image: ubuntu:20.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py38-django22
# Debian Bullseye
py39-django22:
py39-django42:
stage: test
image: debian:bullseye
before_script:
@ -52,11 +20,45 @@ py39-django22:
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py39-django22
script: tox -e py39-django42
# Ubuntu 22.04
py310-django42:
stage: test
image: ubuntu:22.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py310-django42
# Debian Bookworm
py311-django42:
stage: test
image: debian:bookworm
before_script:
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py311-django42
linters:
stage: quality-assurance
image: debian:buster-backports
image: debian:bookworm
before_script:
- apt-get update && apt-get install -y tox
script: tox -e linters

View File

@ -4,13 +4,14 @@
from datetime import timedelta
from random import shuffle
from bootstrap_datepicker_plus.widgets import DateTimePickerInput
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from member.models import Club
from note.models import Note, NoteUser
from note_kfet.inputs import Autocomplete, DateTimePickerInput
from note_kfet.inputs import Autocomplete
from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend

View File

@ -2,7 +2,8 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings
from django.conf.urls import url, include
from django.conf.urls import include
from django.urls import re_path
from rest_framework import routers
from .views import UserInformationView
@ -47,7 +48,7 @@ app_name = 'api'
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
url('^', include(router.urls)),
url('^me/', UserInformationView.as_view()),
url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
re_path('^', include(router.urls)),
re_path('^me/', UserInformationView.as_view()),
re_path('^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

View File

@ -3,7 +3,7 @@
import io
from PIL import Image, ImageSequence
from bootstrap_datepicker_plus.widgets import DatePickerInput
from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
@ -13,8 +13,9 @@ from django.forms import CheckboxSelectMultiple
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, Alias
from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput
from note_kfet.inputs import Autocomplete, AmountInput
from permission.models import PermissionMask, Role
from PIL import Image, ImageSequence
from .models import Profile, Club, Membership
@ -32,7 +33,7 @@ class UserForm(forms.ModelForm):
# Django usernames can only contain letters, numbers, @, ., +, - and _.
# We want to allow users to have uncommon and unpractical usernames:
# That is their problem, and we have normalized aliases for us.
return super()._get_validation_exclusions() + ["username"]
return super()._get_validation_exclusions() | {"username"}
class Meta:
model = User

View File

@ -26,7 +26,7 @@ from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm,\
from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm, \
CustomAuthenticationForm, MembershipRolesForm
from .models import Club, Membership
from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable

View File

@ -13,7 +13,7 @@ from rest_framework import status
from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet
from permission.backends import PermissionBackend
from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer,\
from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer, \
TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer, \
TrustSerializer
from ..models.notes import Note, Alias, NoteUser, NoteClub, NoteSpecial, Trust

View File

@ -2,12 +2,13 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from datetime import datetime
from bootstrap_datepicker_plus.widgets import DateTimePickerInput
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.forms import CheckboxSelectMultiple
from django.utils.timezone import make_aware
from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import Autocomplete, AmountInput, DateTimePickerInput
from note_kfet.inputs import Autocomplete, AmountInput
from .models import TransactionTemplate, NoteClub, Alias

View File

@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
name="{{ widget.name }}"
{# Other attributes are loaded #}
{% for name, value in widget.attrs.items %}
{% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %}
{% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}>
<div class="input-group-append">
<span class="input-group-text"></span>

View File

@ -10,7 +10,7 @@ from django.urls import reverse
from django.utils import timezone
from permission.models import Role
from ..api.views import AliasViewSet, ConsumerViewSet, NotePolymorphicViewSet, TemplateCategoryViewSet,\
from ..api.views import AliasViewSet, ConsumerViewSet, NotePolymorphicViewSet, TemplateCategoryViewSet, \
TransactionTemplateViewSet, TransactionViewSet
from ..models import NoteUser, Transaction, TemplateCategory, TransactionTemplate, RecurrentTransaction, \
MembershipTransaction, SpecialTransaction, NoteSpecial, Alias, Note

View File

@ -44,6 +44,8 @@ class PermissionOAuth2Validator(OAuth2Validator):
subset of permissions.
"""
oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0
valid_scopes = set()
for t in Permission.PERMISSION_TYPES:

View File

@ -5,7 +5,7 @@ from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from api.viewsets import ReadProtectedModelViewSet
from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer,\
from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer, \
SogeCreditSerializer
from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit

View File

@ -3,8 +3,8 @@
from django.urls import path
from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceDeleteView, InvoiceRenderView,\
RemittanceListView, RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView,\
from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceDeleteView, InvoiceRenderView, \
RemittanceListView, RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView, \
UnlinkTransactionToRemittanceView, SogeCreditListView, SogeCreditManageView
app_name = 'treasury'

View File

@ -1,13 +1,14 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from bootstrap_datepicker_plus.widgets import DatePickerInput
from django import forms
from django.contrib.auth.models import User
from django.db.models import Q
from django.forms import CheckboxSelectMultiple
from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, NoteUser
from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget
from note_kfet.inputs import AmountInput, Autocomplete, ColorWidget
from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole

View File

@ -439,7 +439,7 @@ class TestWEIRegistration(TestCase):
emergency_contact_phone='+33123456789',
))
self.assertEqual(response.status_code, 200)
self.assertTrue("This user can&#39;t be in her/his first year since he/she has already participated to a WEI."
self.assertTrue("This user can&#x27;t be in her/his first year since he/she has already participated to a WEI."
in str(response.context["form"].errors))
# Check that if the WEI is started, we can't register anyone
@ -635,7 +635,7 @@ class TestWEIRegistration(TestCase):
))
self.assertEqual(response.status_code, 200)
self.assertFalse(response.context["form"].is_valid())
self.assertTrue("This team doesn&#39;t belong to the given bus." in str(response.context["form"].errors))
self.assertTrue("This team doesn&#x27;t belong to the given bus." in str(response.context["form"].errors))
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
roles=[WEIRole.objects.get(name="GC WEI").id],

View File

@ -82,7 +82,7 @@ msgstr "peut inviter"
#: apps/activity/models.py:44
#: apps/activity/templates/activity/includes/activity_info.html:46
msgid "guest entry fee"
msgstr "cotisation de l'entrée invité"
msgstr "cotisation de l'entrée invitée"
#: apps/activity/models.py:49
msgid "activity type"
@ -119,12 +119,12 @@ msgstr "type"
#: apps/wei/models.py:171 apps/wei/templates/wei/attribute_bus_1A.html:13
#: apps/wei/templates/wei/survey.html:15
msgid "user"
msgstr "utilisateur"
msgstr "utilisateur·ice"
#: apps/activity/models.py:96
#: apps/activity/templates/activity/includes/activity_info.html:36
msgid "organizer"
msgstr "organisateur"
msgstr "organisateur·ice"
#: apps/activity/models.py:97
msgid "Club that organizes the activity. The entry fees will go to this club."
@ -188,7 +188,7 @@ msgstr "entrées"
#: apps/activity/models.py:193
#, python-brace-format
msgid "Entry for {guest}, invited by {note} to the activity {activity}"
msgstr "Entrée pour {guest}, invité par {note} à l'activité {activity}"
msgstr "Entrée pour {guest}, invité·e par {note} à l'activité {activity}"
#: apps/activity/models.py:195
#, python-brace-format
@ -197,7 +197,7 @@ msgstr "Entrée de la note {note} pour l'activité « {activity} »"
#: apps/activity/models.py:202
msgid "Already entered on "
msgstr "Déjà rentré le "
msgstr "Déjà rentré·e le "
#: apps/activity/models.py:202 apps/activity/tables.py:56
msgid "{:%Y-%m-%d %H:%M:%S}"
@ -228,11 +228,11 @@ msgstr "hôte"
#: apps/activity/models.py:256
msgid "guest"
msgstr "invité"
msgstr "invité·e"
#: apps/activity/models.py:257
msgid "guests"
msgstr "invités"
msgstr "invité·e·s"
#: apps/activity/models.py:310
msgid "Invitation"
@ -252,7 +252,7 @@ msgstr "Supprimer"
#: apps/activity/tables.py:56
msgid "Entered on "
msgstr "Entré le "
msgstr "Entré·e le "
#: apps/activity/tables.py:58
msgid "remove"
@ -285,11 +285,11 @@ msgstr "Solde du compte"
#: apps/activity/templates/activity/activity_detail.html:15
msgid "Guests list"
msgstr "Liste des invités"
msgstr "Liste des invité·e·s"
#: apps/activity/templates/activity/activity_detail.html:33
msgid "Guest deleted"
msgstr "Invité supprimé"
msgstr "Invité·e supprimé·e"
#: apps/activity/templates/activity/activity_entry.html:14
#: apps/note/models/transactions.py:261
@ -324,7 +324,7 @@ msgstr "Retour à la page de l'activité"
#: apps/activity/templates/activity/activity_entry.html:129
msgid "Entry done, but caution: the user is not a Kfet member."
msgstr ""
"Entrée effectuée, mais attention : la personne n'est pas un adhérent Kfet."
"Entrée effectuée, mais attention : la personne n'est pas un·e adhérent·e Kfet."
#: apps/activity/templates/activity/activity_entry.html:132
msgid "Entry done!"
@ -365,7 +365,7 @@ msgstr "Toutes les activités"
#: apps/activity/templates/activity/includes/activity_info.html:32
msgid "creater"
msgstr "créateur"
msgstr "créateur·ice"
#: apps/activity/templates/activity/includes/activity_info.html:53
msgid "opened"
@ -419,7 +419,7 @@ msgstr "Invitation pour l'activité « {} »"
#: apps/activity/views.py:178
msgid "You are not allowed to display the entry interface for this activity."
msgstr ""
"Vous n'êtes pas autorisé à afficher l'interface des entrées pour cette "
"Vous n'êtes pas autorisé·e à afficher l'interface des entrées pour cette "
"activité."
#: apps/activity/views.py:181
@ -500,12 +500,12 @@ msgstr "Les logs ne peuvent pas être détruits."
#: apps/member/admin.py:50 apps/member/models.py:232
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "cotisation pour adhérer (normalien élève)"
msgstr "cotisation pour adhérer (normalien·ne élève)"
#: apps/member/admin.py:51 apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "cotisation pour adhérer (normalien étudiant)"
msgstr "cotisation pour adhérer (normalien·ne étudiant·e)"
#: apps/member/admin.py:65 apps/member/models.py:325
msgid "roles"
@ -517,7 +517,7 @@ msgstr "cotisation"
#: apps/member/apps.py:14 apps/wei/tables.py:226 apps/wei/tables.py:257
msgid "member"
msgstr "adhérent"
msgstr "adhérent·e"
#: apps/member/forms.py:24
msgid "Permission mask"
@ -542,7 +542,7 @@ msgid ""
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"available here in pdf</a>"
msgstr ""
"Cochez après avoir lu la chartre anti-VSS <a href=https://perso."
"Cochez après avoir lu la charte anti-VSS <a href=https://perso."
"crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> disponible en pdf ici</"
"a>"
@ -587,7 +587,7 @@ msgstr "Pas de rechargement"
#: apps/member/forms.py:182
msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utilisateur avant l'adhésion."
msgstr "Vous pouvez créditer la note de l'utilisateur·ice avant l'adhésion."
#: apps/member/forms.py:186 apps/registration/forms.py:85
#: apps/wei/forms/registration.py:97
@ -602,7 +602,7 @@ msgstr "Banque"
#: apps/member/forms.py:230
msgid "User"
msgstr "Utilisateur"
msgstr "Utilisateur·ice"
#: apps/member/forms.py:244
msgid "Roles"
@ -731,11 +731,11 @@ msgstr "adresse"
#: apps/registration/templates/registration/future_profile_detail.html:43
#: apps/wei/templates/wei/weimembership_form.html:47
msgid "paid"
msgstr "payé"
msgstr "payé·e"
#: apps/member/models.py:90
msgid "Tells if the user receive a salary."
msgstr "Indique si l'utilisateur perçoit un salaire."
msgstr "Indique si l'utilisateur·ice perçoit un salaire."
#: apps/member/models.py:99 apps/treasury/tables.py:143
msgid "No"
@ -754,7 +754,7 @@ msgid ""
"Register on the mailing list to stay informed of the events of the campus (1 "
"mail/week)"
msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des événements sur "
"S'inscrire sur la liste de diffusion pour rester informé·e des événements sur "
"le campus (1 mail par semaine)"
#: apps/member/models.py:108
@ -762,7 +762,7 @@ msgid ""
"Register on the mailing list to stay informed of the sport events of the "
"campus (1 mail/week)"
msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités "
"S'inscrire sur la liste de diffusion pour rester informé·e des actualités "
"sportives sur le campus (1 mail par semaine)"
#: apps/member/models.py:113
@ -770,7 +770,7 @@ msgid ""
"Register on the mailing list to stay informed of the art events of the "
"campus (1 mail/week)"
msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités "
"S'inscrire sur la liste de diffusion pour rester informé·e des actualités "
"artistiques sur le campus (1 mail par semaine)"
#: apps/member/models.py:117
@ -795,7 +795,7 @@ msgstr "Charte VSS lue"
#: apps/member/models.py:142 apps/member/models.py:143
msgid "user profile"
msgstr "profil utilisateur"
msgstr "profil utilisateur·ice"
#: apps/member/models.py:177
msgid "Activate your Note Kfet account"
@ -839,7 +839,7 @@ msgstr "début de l'adhésion"
#: apps/member/models.py:252
msgid "Date from which the members can renew their membership."
msgstr ""
"Date à partir de laquelle les adhérents peuvent renouveler leur adhésion."
"Date à partir de laquelle les adhérent·e·s peuvent renouveler leur adhésion."
#: apps/member/models.py:258
#: apps/member/templates/member/includes/club_info.html:21
@ -849,7 +849,7 @@ msgstr "fin de l'adhésion"
#: apps/member/models.py:259
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Date maximale d'une fin d'adhésion, après laquelle les adhérents doivent la "
"Date maximale d'une fin d'adhésion, après laquelle les adhérent·e·s doivent la "
"renouveler."
#: apps/member/models.py:263 apps/member/models.py:319
@ -889,11 +889,11 @@ msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:376 apps/member/views.py:712
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
msgstr "L'utilisateur·ice est déjà membre du club"
#: apps/member/models.py:388 apps/member/views.py:721
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
msgstr "L'utilisateur·ice n'est pas membre du club parent"
#: apps/member/tables.py:139
msgid "Renew"
@ -906,7 +906,7 @@ msgid ""
"%(pretty_fee)s will be charged to renew automatically the membership in this/"
"these club·s."
msgstr ""
"Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Un "
"Cet·te utilisateur·ice n'est pas membre du/des club·s parent·s %(clubs)s. Un "
"montant supplémentaire de %(pretty_fee)s sera débité afin de renouveler "
"automatiquement l'adhésion dans ce·s club·s."
@ -916,7 +916,7 @@ msgid ""
"The user is not a member of the club·s %(clubs)s. Please create the required "
"memberships, otherwise it will fail."
msgstr ""
"Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Merci de "
"Cet·te utilisateur·ice n'est pas membre du/des club·s parent·s %(clubs)s. Merci de "
"d'abord créer l'adhésion requise, sinon cette adhésion va échouer."
#: apps/member/templates/member/add_members.html:29
@ -934,7 +934,7 @@ msgid ""
"This club has parents %(clubs)s. Please make sure that the user is a member "
"of this or these club·s, otherwise the creation of this membership will fail."
msgstr ""
"Ce club a pour parents %(clubs)s. Merci de vous assurer que l'utilisateur "
"Ce club a pour parents %(clubs)s. Merci de vous assurer que l'utilisateur·ice "
"est membre de ce·s club·s, sinon la création de cette adhésion va échouer."
#: apps/member/templates/member/base.html:17
@ -956,7 +956,7 @@ msgstr "Voir le profil"
#: apps/member/templates/member/base.html:57
msgid "Add member"
msgstr "Ajouter un membre"
msgstr "Ajouter un·e membre"
#: apps/member/templates/member/base.html:72
#: apps/member/templates/member/base.html:93
@ -983,8 +983,8 @@ msgid ""
"If you use the force mode, the user won't be able to unlock the note by "
"itself."
msgstr ""
"Si vous verrouillez la note de force, l'utilisateur ne pourra plus la "
"déverrouiller lui-même."
"Si vous verrouillez la note de force, l'utilisateur·ice ne pourra plus la "
"déverrouiller soi-même."
#: apps/member/templates/member/base.html:110
#: apps/member/templates/member/base.html:137 apps/treasury/forms.py:91
@ -1165,7 +1165,7 @@ msgstr "Recadrer et envoyer"
#: apps/registration/templates/registration/future_profile_detail.html:28
#: apps/wei/templates/wei/weimembership_form.html:26
msgid "This user doesn't have confirmed his/her e-mail address."
msgstr "Cet utilisateur n'a pas encore confirmé son adresse e-mail."
msgstr "Cet·te utilisateur·ice n'a pas encore confirmé son adresse e-mail."
#: apps/member/templates/member/profile_detail.html:13
#: apps/registration/templates/registration/future_profile_detail.html:29
@ -1179,7 +1179,7 @@ msgstr "Voir mes adhésions"
#: apps/member/templates/member/profile_trust.html:10
msgid "Add friends"
msgstr "Ajouter des amis"
msgstr "Ajouter des ami·e·s"
#: apps/member/templates/member/profile_trust.html:28
msgid ""
@ -1191,12 +1191,12 @@ msgid ""
msgstr ""
"Ajouter quelqu'un⋅e en ami⋅e lui permet de me prélever de l'argent (tant que "
"ma note reste positive). Ceci sert à simplifier les remboursements entre "
"ami⋅es via note. En effet, une personne peut effectuer tous les transferts "
"ami⋅e·s via note. En effet, une personne peut effectuer tous les transferts "
"sans posséder de droits supplémentaires."
#: apps/member/templates/member/profile_trust.html:39
msgid "People having you as a friend"
msgstr "Personnes vous ayant ajouté"
msgstr "Personnes vous ayant ajouté·e"
#: apps/member/templates/member/profile_update.html:18
msgid "Save Changes"
@ -1212,11 +1212,11 @@ msgstr "Cette adresse doit être valide."
#: apps/member/views.py:139
msgid "Profile detail"
msgstr "Détails de l'utilisateur"
msgstr "Détails de l'utilisateur·ice"
#: apps/member/views.py:205
msgid "Search user"
msgstr "Chercher un utilisateur"
msgstr "Chercher un·e utilisateur·ice"
#: apps/member/views.py:253
msgid "Note friendships"
@ -1248,14 +1248,14 @@ msgstr "Modifier le club"
#: apps/member/views.py:574
msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club"
msgstr "Ajouter un·e nouvelle·au membre au club"
#: apps/member/views.py:703 apps/wei/views.py:973
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"Cet·te utilisateur·ice n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif."
#: apps/member/views.py:725
@ -1268,7 +1268,7 @@ msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:880
msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club"
msgstr "Gérer les rôles d'un·e utilisateur·ice dans le club"
#: apps/member/views.py:905
msgid "Members of the club"
@ -1343,7 +1343,7 @@ msgstr "en centimes, argent crédité pour cette instance"
#: apps/note/models/notes.py:37
msgid "last negative date"
msgstr "dernier date de négatif"
msgstr "dernière date de négatif"
#: apps/note/models/notes.py:38
msgid "last time the balance was negative"
@ -1359,7 +1359,7 @@ msgstr "créée le"
#: apps/note/models/notes.py:58
msgid "active"
msgstr "actif"
msgstr "actif·ve"
#: apps/note/models/notes.py:61
msgid ""
@ -1379,8 +1379,8 @@ msgstr ""
#: apps/note/models/notes.py:70
msgid "The note is blocked by the the BDE and can't be manually reactivated."
msgstr ""
"La note est bloquée de force par le BDE et ne peut pas être débloquée par le "
"possesseur de la note."
"La note est bloquée de force par le BDE et ne peut pas être débloquée par le·a "
"possesseur·ice de la note."
#: apps/note/models/notes.py:78
msgid "notes"
@ -1392,11 +1392,11 @@ msgstr "Cet alias est déjà pris."
#: apps/note/models/notes.py:152
msgid "one's note"
msgstr "note d'un utilisateur"
msgstr "note d'un·e utilisateur·ice"
#: apps/note/models/notes.py:153
msgid "users note"
msgstr "notes des utilisateurs"
msgstr "notes des utilisateur·ice·s"
#: apps/note/models/notes.py:159
#, python-format
@ -1430,7 +1430,7 @@ msgstr "note"
#: apps/note/models/notes.py:239
msgid "trusted"
msgstr "ami"
msgstr "ami·e"
#: apps/note/models/notes.py:243
msgid "frienship"
@ -1553,7 +1553,7 @@ msgid ""
"The destination of this transaction must equal to the destination of the "
"template."
msgstr ""
"Le destinataire de cette transaction doit être identique à celui du bouton "
"Le·a destinataire de cette transaction doit être identique à celui du bouton "
"utilisé."
#: apps/note/models/transactions.py:290
@ -1582,7 +1582,7 @@ msgid ""
"payment method and a User or a Club"
msgstr ""
"Une transaction spéciale n'est possible que entre une note associée à un "
"mode de paiement et un utilisateur ou un club"
"mode de paiement et un·e utilisateur·ice ou un club"
#: apps/note/models/transactions.py:357 apps/note/models/transactions.py:360
#: apps/note/models/transactions.py:363 apps/wei/views.py:978
@ -1624,7 +1624,7 @@ msgstr "Supprimer"
#: apps/note/tables.py:191
msgid "Trust back"
msgstr "Ajouter en ami"
msgstr "Ajouter en ami·e"
#: apps/note/tables.py:211
msgid "Add back"
@ -1706,11 +1706,11 @@ msgstr "Mail généré par la Note Kfet le"
#: apps/note/templates/note/transaction_form.html:58
#: apps/note/templates/note/transaction_form.html:178
msgid "Select emitters"
msgstr "Sélection des émetteurs"
msgstr "Sélection des émetteur·ice·s"
#: apps/note/templates/note/transaction_form.html:73
msgid "I am the emitter"
msgstr "Je suis l'émetteur"
msgstr "Je suis l'émetteur·ice"
#: apps/note/templates/note/transaction_form.html:85
#: apps/note/templates/note/transaction_form.html:180
@ -1735,7 +1735,7 @@ msgstr "Nom"
#: apps/note/templates/note/transaction_form.html:177
msgid "Select emitter"
msgstr "Sélection de l'émetteur"
msgstr "Sélection de l'émetteur·ice"
#: apps/note/templates/note/transaction_form.html:179
msgid "Select receiver"
@ -1873,7 +1873,7 @@ msgid ""
"is expired."
msgstr ""
"Indique si la permission doit être attribuée même si l'adhésion de "
"l'utilisateur est expirée."
"l'utilisateur·ice est expirée."
#: apps/permission/models.py:182
#: apps/permission/templates/permission/all_rights.html:89
@ -1931,16 +1931,16 @@ msgstr ""
#: apps/permission/templates/permission/all_rights.html:12
msgid "Users that have surnormal rights"
msgstr "Liste des utilisateurs ayant des droits surnormaux"
msgstr "Liste des utilisateur·ice·s ayant des droits surnormaux"
#: apps/permission/templates/permission/all_rights.html:16
msgid "Superusers have all rights on everything, to manage the website."
msgstr ""
"Les super-utilisateurs ont tous les droits sur tout, afin de gérer le site."
"Les super-utilisateur·ice·s ont tous les droits sur tout, afin de gérer le site."
#: apps/permission/templates/permission/all_rights.html:21
msgid "Superusers"
msgstr "Super-utilisateurs"
msgstr "Super-utilisateur·ice·s"
#: apps/permission/templates/permission/all_rights.html:45
msgid "Roles description"
@ -2095,7 +2095,7 @@ msgstr "Valider le compte"
#: apps/registration/templates/registration/future_profile_detail.html:63
msgid ""
"The user declared that he/she opened a bank account in the Société générale."
msgstr "L'utilisateur a déclaré avoir ouvert un compte à la société générale."
msgstr "L'utilisateur·ice a déclaré avoir ouvert un compte à la société générale."
#: apps/registration/templates/registration/future_profile_detail.html:73
#: apps/wei/templates/wei/weimembership_form.html:127
@ -2105,7 +2105,7 @@ msgstr "Valider l'inscription"
#: apps/registration/templates/registration/future_user_list.html:9
msgid "New user"
msgstr "Nouvel utilisateur"
msgstr "Nouvel·le utilisateur·ice"
#: apps/registration/templates/registration/mails/email_validation_email.html:12
#: apps/registration/templates/registration/mails/email_validation_email.txt:3
@ -2149,7 +2149,7 @@ msgstr "L'équipe de la Note Kfet."
#: apps/registration/views.py:41
msgid "Register new user"
msgstr "Enregistrer un nouvel utilisateur"
msgstr "Enregistrer un·e nouvel·le utilisateur·ice"
#: apps/registration/views.py:99
msgid "Email validation"
@ -2173,11 +2173,11 @@ msgstr "Renvoyer le lien de validation"
#: apps/registration/views.py:182
msgid "Pre-registered users list"
msgstr "Liste des utilisateurs en attente d'inscription"
msgstr "Liste des utilisateur·ice·s en attente d'inscription"
#: apps/registration/views.py:206
msgid "Unregistered users"
msgstr "Utilisateurs en attente d'inscription"
msgstr "Utilisateur·ice·s en attente d'inscription"
#: apps/registration/views.py:219
msgid "Registration detail"
@ -2360,14 +2360,14 @@ msgstr "Crédits de la Société générale"
#: apps/treasury/models.py:315
#, python-brace-format
msgid "Soge credit for {user}"
msgstr "Crédit de la société générale pour l'utilisateur {user}"
msgstr "Crédit de la société générale pour l'utilisateur·ice {user}"
#: apps/treasury/models.py:445
msgid ""
"This user doesn't have enough money to pay the memberships with its note. "
"Please ask her/him to credit the note before invalidating this credit."
msgstr ""
"Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa "
"Cet·te utilisateur·ice n'a pas assez d'argent pour payer les adhésions avec sa "
"note. Merci de lui demander de recharger sa note avant d'invalider ce crédit."
#: apps/treasury/tables.py:20
@ -2519,12 +2519,12 @@ msgid ""
"If this credit is validated, then the user won't be able to ask for a credit "
"from the Société générale."
msgstr ""
"Si ce crédit est validé, alors l'utilisateur ne pourra plus demander d'être "
"crédité par la Société générale à l'avenir."
"Si ce crédit est validé, alors l'utilisateur·ice ne pourra plus demander d'être "
"crédité·e par la Société générale à l'avenir."
#: apps/treasury/templates/treasury/sogecredit_detail.html:44
msgid "If you think there is an error, please contact the \"respos info\"."
msgstr "Si vous pensez qu'il y a une erreur, merci de contacter un respo info."
msgstr "Si vous pensez qu'il y a une erreur, merci de contacter un·e respo info."
#: apps/treasury/templates/treasury/sogecredit_detail.html:50
msgid "This credit is already validated."
@ -2535,13 +2535,13 @@ msgid ""
"Warning: if you don't validate this credit, the note of the user doesn't "
"have enough money to pay its memberships."
msgstr ""
"Attention : si vous ne validez pas ce crédit, la note de l'utilisateur n'a "
"Attention : si vous ne validez pas ce crédit, la note de l'utilisateur·ice n'a "
"pas assez d'argent pour payer les adhésions."
#: apps/treasury/templates/treasury/sogecredit_detail.html:56
msgid "Please ask the user to credit its note before deleting this credit."
msgstr ""
"Merci de demander à l'utilisateur de recharger sa note avant de supprimer la "
"Merci de demander à l'utilisateur·ice de recharger sa note avant de supprimer la "
"demande de crédit."
#: apps/treasury/templates/treasury/sogecredit_detail.html:63
@ -2560,7 +2560,7 @@ msgstr "Filtrer avec uniquement les crédits non valides"
#: apps/treasury/templates/treasury/sogecredit_list.html:50
msgid "There is no matched user that have asked for a Société générale credit."
msgstr ""
"Il n'y a pas d'utilisateur trouvé ayant demandé un crédit de la Société "
"Il n'y a pas d'utilisateur·ice trouvé·e ayant demandé un crédit de la Société "
"générale."
#: apps/treasury/templates/treasury/sogecredit_list.html:63
@ -2582,7 +2582,7 @@ msgstr "Liste des factures"
#: apps/treasury/views.py:105 apps/treasury/views.py:275
#: apps/treasury/views.py:401
msgid "You are not able to see the treasury interface."
msgstr "Vous n'êtes pas autorisé à voir l'interface de trésorerie."
msgstr "Vous n'êtes pas autorisé·e à voir l'interface de trésorerie."
#: apps/treasury/views.py:115
msgid "Update an invoice"
@ -2621,7 +2621,7 @@ msgstr "WEI"
#: apps/wei/forms/registration.py:35
msgid "The selected user is not validated. Please validate its account first"
msgstr ""
"L'utilisateur sélectionné n'est pas validé. Merci de d'abord valider son "
"L'utilisateur·ice sélectionné·e n'est pas validé·e. Merci de d'abord valider son "
"compte"
#: apps/wei/forms/registration.py:59 apps/wei/models.py:126
@ -2634,8 +2634,8 @@ msgid ""
"This choice is not definitive. The WEI organizers are free to attribute for "
"you a bus and a team, in particular if you are a free eletron."
msgstr ""
"Ce choix n'est pas définitif. Les organisateurs du WEI sont libres de vous "
"attribuer un bus et une équipe, en particulier si vous êtes un électron "
"Ce choix n'est pas définitif. Les organisateur·ice·s du WEI sont libres de vous "
"attribuer un bus et une équipe, en particulier si vous êtes un·e électron "
"libre."
#: apps/wei/forms/registration.py:67
@ -2787,7 +2787,7 @@ msgstr "première année"
#: apps/wei/models.py:249
msgid "Tells if the user is new in the school."
msgstr "Indique si l'utilisateur est nouveau dans l'école."
msgstr "Indique si l'utilisateur·ice est nouveau dans l'école."
#: apps/wei/models.py:254
msgid "registration information"
@ -2803,11 +2803,11 @@ msgstr ""
#: apps/wei/models.py:261
msgid "WEI User"
msgstr "Participant au WEI"
msgstr "Participant·e au WEI"
#: apps/wei/models.py:262
msgid "WEI Users"
msgstr "Participants au WEI"
msgstr "Participant·e·s au WEI"
#: apps/wei/models.py:334
msgid "team"
@ -2827,19 +2827,19 @@ msgstr "Adhésions au WEI"
#: apps/wei/tables.py:105
msgid "The user does not have enough money."
msgstr "L'utilisateur n'a pas assez d'argent."
msgstr "L'utilisateur·ice n'a pas assez d'argent."
#: apps/wei/tables.py:108
msgid ""
"The user is in first year. You may validate the credit, the algorithm will "
"run later."
msgstr ""
"L'utilisateur est en première année, vous pouvez valider le crédit, "
"L'utilisateur·ice est en première année, vous pouvez valider le crédit, "
"l'algorithme tournera plus tard."
#: apps/wei/tables.py:111
msgid "The user has enough money, you can validate the registration."
msgstr "L'utilisateur a assez d'argent, l'inscription est possible."
msgstr "L'utilisateur·ice a assez d'argent, l'inscription est possible."
#: apps/wei/tables.py:143
msgid "Year"
@ -2860,19 +2860,19 @@ msgstr "Nombre de membres"
#: apps/wei/tables.py:226 apps/wei/tables.py:257
msgid "members"
msgstr "adhérents"
msgstr "adhérent·e·s"
#: apps/wei/tables.py:287
msgid "suggested first year"
msgstr "1A suggérés"
msgstr "1A suggéré·e·s"
#: apps/wei/tables.py:293
msgid "validated first year"
msgstr "1A validés"
msgstr "1A validé·e·s"
#: apps/wei/tables.py:299
msgid "validated staff"
msgstr "2A+ validés"
msgstr "2A+ validé·e·s"
#: apps/wei/tables.py:310
msgid "free seats"
@ -3052,7 +3052,7 @@ msgstr "L'inscription a déjà été validée et ne peut pas être dévalidée."
#: apps/wei/templates/wei/weimembership_form.html:132
msgid "The user joined the bus"
msgstr "L'utilisateur a rejoint le bus"
msgstr "L'utilisateur·ice a rejoint le bus"
#: apps/wei/templates/wei/weimembership_form.html:133
msgid "in the team"
@ -3097,7 +3097,7 @@ msgstr ""
#: apps/wei/templates/wei/weimembership_form.html:166
msgid "The user didn't give her/his caution check."
msgstr "L'utilisateur n'a pas donné son chèque de caution."
msgstr "L'utilisateur·ice n'a pas donné son chèque de caution."
#: apps/wei/templates/wei/weimembership_form.html:174
msgid ""
@ -3105,7 +3105,7 @@ msgid ""
"membership will be processed automatically, the WEI registration includes "
"the membership fee."
msgstr ""
"Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. "
"Cet·te utilisateur·ice n'est pas membre du club Kfet pour l'année à venir. "
"L'adhésion va être faite automatiquement, l'inscription au WEI inclut le "
"coût d'adhésion."
@ -3199,7 +3199,7 @@ msgid ""
"This user can't be in her/his first year since he/she has already "
"participated to a WEI."
msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'il a déjà "
"Cet·te utilisateur·ice ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI."
#: apps/wei/views.py:578
@ -3313,7 +3313,7 @@ msgstr "La note du BDE de l'ENS Paris-Saclay."
#: note_kfet/templates/base.html:78
msgid "Users"
msgstr "Utilisateurs"
msgstr "Utilisateur·ice·s"
#: note_kfet/templates/base.html:84
msgid "Clubs"
@ -3351,7 +3351,7 @@ msgid ""
"You are not a BDE member anymore. Please renew your membership if you want "
"to use the note."
msgstr ""
"Vous n'êtes plus adhérent BDE. Merci de réadhérer si vous voulez profiter de "
"Vous n'êtes plus adhérent·e BDE. Merci de réadhérer si vous voulez profiter de "
"la note."
#: note_kfet/templates/base.html:165
@ -3370,7 +3370,7 @@ msgid ""
"last a few days. Please make sure that you go to the end of the account "
"creation."
msgstr ""
"Vous avez déclaré que vous avez ouvert un compte bancaire à la société "
"Vous avez déclaré·e que vous avez ouvert un compte bancaire à la société "
"générale. La banque n'a pas encore validé la création du compte auprès du "
"BDE, l'adhésion et le WEI ne sont donc pas encore payés. Cette procédure de "
"vérification peut durer quelques jours. Merci de vous assurer de bien aller "
@ -3589,7 +3589,7 @@ msgid ""
"you registered with, and check your spam folder."
msgstr ""
"Si vous ne recevez pas d'email, vérifiez que vous avez bien utilisé "
"l'adresse associé à votre compte, et regarder également le dossier spam."
"l'adresse associée à votre compte, et regarder également le dossier spam."
#: note_kfet/templates/registration/password_reset_form.html:13
msgid ""
@ -3610,7 +3610,7 @@ msgid ""
"Kfet and pay the registration fee. You must also validate your email address "
"by following the link you received."
msgstr ""
"Si vous vous êtes déjà inscrits, votre inscription a bien été prise en "
"Si vous vous êtes déjà inscrit·e·s, votre inscription a bien été prise en "
"compte. Le BDE doit d'abord valider votre compte avant que vous puissiez "
"vous connecter. Vous devez vous rendre à la Kfet et payer les frais "
"d'adhésion. Vous devez également valider votre adresse email en suivant le "
@ -3622,7 +3622,7 @@ msgstr ""
#, fuzzy
#~| msgid "People having you as a friend"
#~ msgid "You already have that person as a friend"
#~ msgstr "Personnes vous ayant ajouté"
#~ msgstr "Personnes vous ayant ajouté·e"
#~ msgid ""
#~ "I declare that I opened or I will open soon a bank account in the Société "

View File

@ -25,8 +25,8 @@ admin_site.register(Site, SiteAdmin)
# Add external apps model
if "oauth2_provider" in settings.INSTALLED_APPS:
from oauth2_provider.admin import Application, ApplicationAdmin, Grant, \
GrantAdmin, AccessToken, AccessTokenAdmin, RefreshToken, RefreshTokenAdmin
from oauth2_provider.admin import ApplicationAdmin, GrantAdmin, AccessTokenAdmin, RefreshTokenAdmin
from oauth2_provider.models import Application, Grant, AccessToken, RefreshToken
admin_site.register(Application, ApplicationAdmin)
admin_site.register(Grant, GrantAdmin)
admin_site.register(AccessToken, AccessTokenAdmin)

View File

@ -68,264 +68,3 @@ class ColorWidget(Widget):
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

View File

@ -40,8 +40,9 @@ INSTALLED_APPS = [
# External apps
'bootstrap_datepicker_plus',
'colorfield',
'crispy_bootstrap4',
'crispy_forms',
'django_htcpcp_tea',
# 'django_htcpcp_tea',
'django_tables2',
'mailer',
'phonenumber_field',
@ -90,12 +91,14 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware',
'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware',
'note_kfet.middlewares.SessionMiddleware',
'note_kfet.middlewares.LoginByIPMiddleware',
'note_kfet.middlewares.TurbolinksMiddleware',
'note_kfet.middlewares.ClacksMiddleware',
]
if "django_htcpcp_tea" in INSTALLED_APPS:
MIDDLEWARE.append('django_htcpcp_tea.middleware.HTCPCPTeaMiddleware')
ROOT_URLCONF = 'note_kfet.urls'
@ -263,6 +266,9 @@ OAUTH2_PROVIDER = {
'REFRESH_TOKEN_EXPIRE_SECONDS': timedelta(days=14),
}
# PKCE (fix a breaking change of django-oauth-toolkit 2.0.0)
PKCE_REQUIRED = False
# Take control on how widget templates are sourced
# See https://docs.djangoproject.com/en/2.2/ref/forms/renderers/#templatessetting
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
@ -274,6 +280,7 @@ LOGIN_REDIRECT_URL = '/'
SESSION_COOKIE_AGE = 60 * 60 * 3
# Use Crispy Bootstrap4 theme
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap4'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# Use Django Table2 Bootstrap4 theme
@ -295,3 +302,6 @@ PHONENUMBER_DEFAULT_REGION = 'FR'
# We add custom information to CAS, in order to give a normalized name to other services
CAS_AUTH_CLASS = 'member.auth.CustomAuthUser'
# Default field for primary key
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

View File

@ -8,7 +8,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% 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 %}
{% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
aria-describedby="{{widget.attrs.id}}_tooltip">
{% if widget.resetable %}

View File

@ -30,9 +30,6 @@ urlpatterns = [
path('accounts/', include('django.contrib.auth.urls')),
path('api/', include('api.urls')),
path('permission/', include('permission.urls')),
# Make coffee
path('coffee/', include('django_htcpcp_tea.urls')),
]
# During development, serve static and media files
@ -57,6 +54,11 @@ if "debug_toolbar" in settings.INSTALLED_APPS:
path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
if "django_htcpcp_tea" in settings.INSTALLED_APPS:
# Make coffee
urlpatterns.append(
path('coffee/', include('django_htcpcp_tea.urls'))
)
handler400 = bad_request
handler403 = permission_denied

View File

@ -1,19 +1,20 @@
beautifulsoup4~=4.7.1
Django~=2.2.15
django-bootstrap-datepicker-plus~=3.0.5
django-cas-server~=1.2.0
django-colorfield~=0.3.2
django-crispy-forms~=1.7.2
django-extensions>=2.1.4
django-filter~=2.1
django-htcpcp-tea~=0.3.1
django-mailer~=2.0.1
django-oauth-toolkit~=1.3.3
django-phonenumber-field~=5.0.0
django-polymorphic>=2.0.3,<3.0.0
djangorestframework>=3.9.0,<3.13.0
django-rest-polymorphic~=0.1.9
django-tables2~=2.3.1
python-memcached~=1.59
phonenumbers~=8.9.10
Pillow>=5.4.1
beautifulsoup4~=4.12.3
crispy-bootstrap4~=2023.1
Django~=4.2.9
django-bootstrap-datepicker-plus~=5.0.5
#django-cas-server~=2.0.0
django-colorfield~=0.11.0
django-crispy-forms~=2.1.0
django-extensions>=3.2.3
django-filter~=23.5
#django-htcpcp-tea~=0.8.1
django-mailer~=2.3.1
django-oauth-toolkit~=2.3.0
django-phonenumber-field~=7.3.0
django-polymorphic~=3.1.0
djangorestframework~=3.14.0
django-rest-polymorphic~=0.1.10
django-tables2~=2.7.0
python-memcached~=1.62
phonenumbers~=8.13.28
Pillow>=10.2.0

14
tox.ini
View File

@ -1,13 +1,13 @@
[tox]
envlist =
# Debian Buster Python
py37-django22
# Ubuntu 20.04 Python
py38-django22
# Debian Bullseye Python
py39-django22
py39-django42
# Ubuntu 22.04 Python
py310-django42
# Debian Bookworm Python
py311-django42
linters
skipsdist = True