1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-09-27 20:08:19 +02:00

Compare commits

..

11 Commits

Author SHA1 Message Date
Ehouarn
0a261e6ad5 Bugs fixed again (lost in beta) 2025-07-13 16:38:39 +02:00
ehouarn
79f50c27f1 Merge branch 'beta' into 'food_traceability'
# Conflicts:
#   locale/fr/LC_MESSAGES/django.po
2025-07-11 17:00:45 +02:00
Ehouarn
5989721bc9 Easier access to food details 2025-07-11 16:35:49 +02:00
quark
bcc3e7cc53 Merge branch 'food_traceability' into beta 2025-07-11 12:26:55 +02:00
Ehouarn
608804db30 Bugs fixed 2025-07-10 20:05:27 +02:00
quark
82a06c29dd linters 2025-07-09 16:12:55 +02:00
quark
cf9d208586 scopes 2025-07-09 15:57:24 +02:00
quark
432f50e49a propose fix for #134 (partially tested) 2025-07-09 00:15:33 +02:00
quark
883589e08c django-constance and traduction 2025-07-06 16:17:13 +02:00
quark
c36f8c25a2 Add banner #80 (with django-constance 2025-07-05 18:45:36 +02:00
quark
8783a63d7f change CAS template for #133 2025-07-05 13:56:43 +02:00
17 changed files with 472 additions and 91 deletions

View File

@@ -145,7 +145,7 @@ class AddIngredientForms(forms.ModelForm):
polymorphic_ctype__model="transformedfood", polymorphic_ctype__model="transformedfood",
is_ready=False, is_ready=False,
end_of_life='', end_of_life='',
).filter(PermissionBackend.filter_queryset(get_current_request(), TransformedFood, "change")).exclude(pk=pk) ).filter(PermissionBackend.filter_queryset(get_current_request(), Food, "change")).exclude(pk=pk)
class Meta: class Meta:
model = TransformedFood model = TransformedFood

View File

@@ -12,6 +12,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
</h3> </h3>
<div class="card-body"> <div class="card-body">
<ul> <ul>
{% if QR_code %}
<li> {{QR_code}} </li>
{% endif %}
{% for field, value in fields %} {% for field, value in fields %}
<li> {{ field }} : {{ value }}</li> <li> {{ field }} : {{ value }}</li>
{% endfor %} {% endfor %}

View File

@@ -7,7 +7,52 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
{{ block.super }} <div class="card bg-light">
<h3 class="card-header text-center">
{{ title }}
</h3>
<div class="card-body">
<style>
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
appearance: textfield;
padding: 6px;
border: 1px solid #ccc;
border-radius: 4px;
width: 100px;
}
</style>
<div class="d-flex align-items-center" style="max-width: 300px;">
<form method="get" action="{% url 'food:redirect_view' %}" class="d-flex w-100">
<input type="number" name="slug" placeholder="QR-code" required class="form-control form-control-sm" style="max-width: 120px;">
<button type="submit" class="btn btn-sm btn-primary">{% trans "View food" %}</button>
</form>
</div>
</div>
<div class="card-body">
<input id="searchbar" type="text" class="form-control"
placeholder="{% trans "Search by attribute such as name..." %}">
</div>
{% block extra_inside_card %}
{% endblock %}
<div id="dynamic-table">
{% if table.data %}
{% render_table table %}
{% else %}
<div class="card-body">
<div class="alert alert-warning">
{% trans "There is no results." %}
</div>
</div>
{% endif %}
</div>
</div>
<br> <br>
<div class="card bg-light mb-3"> <div class="card bg-light mb-3">
<h3 class="card-header text-center"> <h3 class="card-header text-center">
@@ -68,4 +113,20 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('goButton').addEventListener('click', function(event) {
event.preventDefault();
const slug = document.getElementById('slugInput').value;
if (slug && !isNaN(slug)) {
window.location.href = `/food/${slug}/`;
} else {
alert("Veuillez entrer un nombre valide.");
}
});
});
</script>
{% endblock %} {% endblock %}

View File

@@ -18,4 +18,5 @@ urlpatterns = [
path('detail/basic/<int:pk>', views.BasicFoodDetailView.as_view(), name='basicfood_view'), path('detail/basic/<int:pk>', views.BasicFoodDetailView.as_view(), name='basicfood_view'),
path('detail/transformed/<int:pk>', views.TransformedFoodDetailView.as_view(), name='transformedfood_view'), path('detail/transformed/<int:pk>', views.TransformedFoodDetailView.as_view(), name='transformedfood_view'),
path('add/ingredient/<int:pk>', views.AddIngredientView.as_view(), name='add_ingredient'), path('add/ingredient/<int:pk>', views.AddIngredientView.as_view(), name='add_ingredient'),
path('redirect/', views.QRCodeRedirectView.as_view(), name='redirect_view'),
] ]

View File

@@ -10,6 +10,7 @@ from django.db.models import Q
from django.http import HttpResponseRedirect, Http404 from django.http import HttpResponseRedirect, Http404
from django.views.generic import DetailView, UpdateView, CreateView from django.views.generic import DetailView, UpdateView, CreateView
from django.views.generic.list import ListView from django.views.generic.list import ListView
from django.views.generic.base import RedirectView
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@@ -454,6 +455,8 @@ class FoodDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context["fields"] = [( context["fields"] = [(
Food._meta.get_field(field).verbose_name.capitalize(), Food._meta.get_field(field).verbose_name.capitalize(),
value) for field, value in fields.items()] value) for field, value in fields.items()]
if self.object.QR_code.exists():
context["QR_code"] = self.object.QR_code.first()
context["meals"] = self.object.transformed_ingredient_inv.all() context["meals"] = self.object.transformed_ingredient_inv.all()
context["update"] = PermissionBackend.check_perm(self.request, "food.change_food") context["update"] = PermissionBackend.check_perm(self.request, "food.change_food")
context["add_ingredient"] = (self.object.end_of_life == '' and PermissionBackend.check_perm(self.request, "food.change_transformedfood")) context["add_ingredient"] = (self.object.end_of_life == '' and PermissionBackend.check_perm(self.request, "food.change_transformedfood"))
@@ -507,3 +510,14 @@ class TransformedFoodDetailView(FoodDetailView):
if Food.objects.filter(pk=kwargs['pk']).count() == 1: if Food.objects.filter(pk=kwargs['pk']).count() == 1:
kwargs['stop_redirect'] = (Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model == 'transformedfood') kwargs['stop_redirect'] = (Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model == 'transformedfood')
return super().get(*args, **kwargs) return super().get(*args, **kwargs)
class QRCodeRedirectView(RedirectView):
"""
Redirects to the QR code creation page from Food List
"""
def get_redirect_url(self, *args, **kwargs):
slug = self.request.GET.get('slug')
if slug:
return reverse_lazy('food:qrcode_create', kwargs={'slug': slug})
return reverse_lazy('food:list')

View File

@@ -18,7 +18,18 @@ class PermissionScopes(BaseScopes):
and can be useful to make queries through the API with limited privileges. and can be useful to make queries through the API with limited privileges.
""" """
def get_all_scopes(self): def get_all_scopes(self, **kwargs):
scopes = {}
if 'scopes' in kwargs:
for scope in kwargs['scopes']:
if scope == 'openid':
scopes['openid'] = "OpenID Connect"
else:
p = Permission.objects.get(id=scope.split('_')[0])
club = Club.objects.get(id=scope.split('_')[1])
scopes[scope] = f"{p.description} (club {club.name})"
return scopes
scopes = {f"{p.id}_{club.id}": f"{p.description} (club {club.name})" scopes = {f"{p.id}_{club.id}": f"{p.description} (club {club.name})"
for p in Permission.objects.all() for club in Club.objects.all()} for p in Permission.objects.all() for club in Club.objects.all()}
scopes['openid'] = "OpenID Connect" scopes['openid'] = "OpenID Connect"

View File

@@ -13,6 +13,7 @@ EXCLUDED = [
'cas_server.serviceticket', 'cas_server.serviceticket',
'cas_server.user', 'cas_server.user',
'cas_server.userattributes', 'cas_server.userattributes',
'constance.constance',
'contenttypes.contenttype', 'contenttypes.contenttype',
'logs.changelog', 'logs.changelog',
'migrations.migration', 'migrations.migration',

View File

@@ -164,14 +164,24 @@ class ScopesView(LoginRequiredMixin, TemplateView):
from oauth2_provider.models import Application from oauth2_provider.models import Application
from .scopes import PermissionScopes from .scopes import PermissionScopes
scopes = PermissionScopes() oidc = False
context["scopes"] = {} context["scopes"] = {}
all_scopes = scopes.get_all_scopes()
for app in Application.objects.filter(user=self.request.user).all(): for app in Application.objects.filter(user=self.request.user).all():
available_scopes = scopes.get_available_scopes(app) available_scopes = PermissionScopes().get_available_scopes(app)
context["scopes"][app] = OrderedDict() context["scopes"][app] = OrderedDict()
items = [(k, v) for (k, v) in all_scopes.items() if k in available_scopes] all_scopes = PermissionScopes().get_all_scopes(scopes=available_scopes)
# items.sort(key=lambda x: (int(x[0].split("_")[1]), int(x[0].split("_")[0]))) scopes = {}
for scope in available_scopes:
scopes[scope] = all_scopes[scope]
# remove OIDC scope for sort
if 'openid' in scopes:
del scopes['openid']
oidc = True
items = [(k, v) for (k, v) in scopes.items()]
items.sort(key=lambda x: (int(x[0].split("_")[1]), int(x[0].split("_")[0])))
# add oidc if necessary
if oidc:
items.append(('openid', PermissionScopes().get_all_scopes(scopes=['openid'])['openid']))
for k, v in items: for k, v in items:
context["scopes"][app][k] = v context["scopes"][app][k] = v

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-07-04 21:47+0200\n" "POT-Creation-Date: 2025-07-11 16:10+0200\n"
"PO-Revision-Date: 2022-04-11 22:05+0200\n" "PO-Revision-Date: 2022-04-11 22:05+0200\n"
"Last-Translator: bleizi <bleizi@crans.org>\n" "Last-Translator: bleizi <bleizi@crans.org>\n"
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n" "Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
@@ -357,7 +357,7 @@ msgstr "Détails de l'activité"
#: apps/note/models/transactions.py:261 #: apps/note/models/transactions.py:261
#: apps/note/templates/note/transaction_form.html:17 #: apps/note/templates/note/transaction_form.html:17
#: apps/note/templates/note/transaction_form.html:152 #: apps/note/templates/note/transaction_form.html:152
#: note_kfet/templates/base.html:78 #: note_kfet/templates/base.html:79
msgid "Transfer" msgid "Transfer"
msgstr "Virement" msgstr "Virement"
@@ -474,7 +474,7 @@ msgstr "Inviter"
msgid "Create new activity" msgid "Create new activity"
msgstr "Créer une nouvelle activité" msgstr "Créer une nouvelle activité"
#: apps/activity/views.py:71 note_kfet/templates/base.html:96 #: apps/activity/views.py:71 note_kfet/templates/base.html:97
msgid "Activities" msgid "Activities"
msgstr "Activités" msgstr "Activités"
@@ -563,7 +563,7 @@ msgstr "Nom"
#, fuzzy #, fuzzy
#| msgid "QR-code number" #| msgid "QR-code number"
msgid "QR code number" msgid "QR code number"
msgstr "numéro de QR-code" msgstr "Numéro de QR-code"
#: apps/food/models.py:23 #: apps/food/models.py:23
msgid "Allergen" msgid "Allergen"
@@ -597,7 +597,7 @@ msgstr "est prêt"
msgid "order" msgid "order"
msgstr "consigne" msgstr "consigne"
#: apps/food/models.py:107 apps/food/views.py:34 #: apps/food/models.py:107 apps/food/views.py:35
#: note_kfet/templates/base.html:72 #: note_kfet/templates/base.html:72
msgid "Food" msgid "Food"
msgstr "Bouffe" msgstr "Bouffe"
@@ -657,61 +657,75 @@ msgstr "QR-codes"
#: apps/food/models.py:286 #: apps/food/models.py:286
#: apps/food/templates/food/transformedfood_update.html:24 #: apps/food/templates/food/transformedfood_update.html:24
msgid "QR-code number" msgid "QR-code number"
msgstr "numéro de QR-code" msgstr "Numéro de QR-code"
#: apps/food/templates/food/food_detail.html:19 #: apps/food/templates/food/food_detail.html:22
msgid "Contained in" msgid "Contained in"
msgstr "Contenu dans" msgstr "Contenu dans"
#: apps/food/templates/food/food_detail.html:26 #: apps/food/templates/food/food_detail.html:29
msgid "Contain" msgid "Contain"
msgstr "Contient" msgstr "Contient"
#: apps/food/templates/food/food_detail.html:35 #: apps/food/templates/food/food_detail.html:38
msgid "Update" msgid "Update"
msgstr "Modifier" msgstr "Modifier"
#: apps/food/templates/food/food_detail.html:40 #: apps/food/templates/food/food_detail.html:43
msgid "Add to a meal" msgid "Add to a meal"
msgstr "Ajouter à un plat" msgstr "Ajouter à un plat"
#: apps/food/templates/food/food_detail.html:45 #: apps/food/templates/food/food_detail.html:48
msgid "Manage ingredients" msgid "Manage ingredients"
msgstr "Gérer les ingrédients" msgstr "Gérer les ingrédients"
#: apps/food/templates/food/food_detail.html:49 #: apps/food/templates/food/food_detail.html:52
msgid "Return to the food list" msgid "Return to the food list"
msgstr "Retour à la liste de nourriture" msgstr "Retour à la liste de nourriture"
#: apps/food/templates/food/food_list.html:14 #: apps/food/templates/food/food_list.html:32
msgid "View food"
msgstr "Voir l'aliment"
#: apps/food/templates/food/food_list.html:37
#: note_kfet/templates/base_search.html:15
msgid "Search by attribute such as name..."
msgstr "Chercher par un attribut tel que le nom..."
#: apps/food/templates/food/food_list.html:49
#: note_kfet/templates/base_search.html:23
msgid "There is no results."
msgstr "Il n'y a pas de résultat."
#: apps/food/templates/food/food_list.html:58
msgid "Meal served" msgid "Meal served"
msgstr "Plat servis" msgstr "Plat servis"
#: apps/food/templates/food/food_list.html:19 #: apps/food/templates/food/food_list.html:63
msgid "New meal" msgid "New meal"
msgstr "Nouveau plat" msgstr "Nouveau plat"
#: apps/food/templates/food/food_list.html:28 #: apps/food/templates/food/food_list.html:72
msgid "There is no meal served." msgid "There is no meal served."
msgstr "Il n'y a pas de plat servi." msgstr "Il n'y a pas de plat servi."
#: apps/food/templates/food/food_list.html:35 #: apps/food/templates/food/food_list.html:79
msgid "Free food" msgid "Free food"
msgstr "Open" msgstr "Open"
#: apps/food/templates/food/food_list.html:42 #: apps/food/templates/food/food_list.html:86
msgid "There is no free food." msgid "There is no free food."
msgstr "Il n'y a pas de bouffe en open" msgstr "Il n'y a pas de bouffe en open"
#: apps/food/templates/food/food_list.html:50 #: apps/food/templates/food/food_list.html:94
msgid "Food of your clubs" msgid "Food of your clubs"
msgstr "Bouffe de tes clubs" msgstr "Bouffe de tes clubs"
#: apps/food/templates/food/food_list.html:56 #: apps/food/templates/food/food_list.html:100
msgid "Food of club" msgid "Food of club"
msgstr "Bouffe du club" msgstr "Bouffe du club"
#: apps/food/templates/food/food_list.html:63 #: apps/food/templates/food/food_list.html:107
msgid "Yours club has not food yet." msgid "Yours club has not food yet."
msgstr "Ton club n'a pas de bouffe pour l'instant" msgstr "Ton club n'a pas de bouffe pour l'instant"
@@ -785,49 +799,49 @@ msgstr "semaines"
msgid "and" msgid "and"
msgstr "et" msgstr "et"
#: apps/food/views.py:119 #: apps/food/views.py:120
msgid "Add a new QRCode" msgid "Add a new QRCode"
msgstr "Ajouter un nouveau QR-code" msgstr "Ajouter un nouveau QR-code"
#: apps/food/views.py:168 #: apps/food/views.py:169
msgid "Add an aliment" msgid "Add an aliment"
msgstr "Ajouter un nouvel aliment" msgstr "Ajouter un nouvel aliment"
#: apps/food/views.py:236 #: apps/food/views.py:228
msgid "Add a meal" msgid "Add a meal"
msgstr "Ajouter un plat" msgstr "Ajouter un plat"
#: apps/food/views.py:276 #: apps/food/views.py:259
msgid "Manage ingredients of:" msgid "Manage ingredients of:"
msgstr "Gestion des ingrédienrs de :" msgstr "Gestion des ingrédienrs de :"
#: apps/food/views.py:290 apps/food/views.py:298 #: apps/food/views.py:273 apps/food/views.py:281
#, python-brace-format #, python-brace-format
msgid "Fully used in {meal}" msgid "Fully used in {meal}"
msgstr "Aliment entièrement utilisé dans : {meal}" msgstr "Aliment entièrement utilisé dans : {meal}"
#: apps/food/views.py:345 #: apps/food/views.py:320
msgid "Add the ingredient:" msgid "Add the ingredient:"
msgstr "Ajouter l'ingrédient" msgstr "Ajouter l'ingrédient"
#: apps/food/views.py:371 #: apps/food/views.py:346
#, python-brace-format #, python-brace-format
msgid "Food fully used in : {meal.name}" msgid "Food fully used in : {meal.name}"
msgstr "Aliment entièrement utilisé dans : {meal.name}" msgstr "Aliment entièrement utilisé dans : {meal.name}"
#: apps/food/views.py:390 #: apps/food/views.py:365
msgid "Update an aliment" msgid "Update an aliment"
msgstr "Modifier un aliment" msgstr "Modifier un aliment"
#: apps/food/views.py:438 #: apps/food/views.py:413
msgid "Details of:" msgid "Details of:"
msgstr "Détails de :" msgstr "Détails de :"
#: apps/food/views.py:448 apps/treasury/tables.py:149 #: apps/food/views.py:423 apps/treasury/tables.py:149
msgid "Yes" msgid "Yes"
msgstr "Oui" msgstr "Oui"
#: apps/food/views.py:450 apps/member/models.py:99 apps/treasury/tables.py:149 #: apps/food/views.py:425 apps/member/models.py:99 apps/treasury/tables.py:149
msgid "No" msgid "No"
msgstr "Non" msgstr "Non"
@@ -2178,7 +2192,7 @@ msgstr "Chercher un bouton"
msgid "Update button" msgid "Update button"
msgstr "Modifier le bouton" msgstr "Modifier le bouton"
#: apps/note/views.py:156 note_kfet/templates/base.html:66 #: apps/note/views.py:156 note_kfet/templates/base.html:67
msgid "Consumptions" msgid "Consumptions"
msgstr "Consommations" msgstr "Consommations"
@@ -2271,7 +2285,7 @@ msgstr "s'applique au club"
msgid "role permissions" msgid "role permissions"
msgstr "permissions par rôles" msgstr "permissions par rôles"
#: apps/permission/signals.py:74 #: apps/permission/signals.py:75
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"You don't have the permission to change the field {field} on this instance " "You don't have the permission to change the field {field} on this instance "
@@ -2280,7 +2294,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du " "Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}." "modèle {app_label}.{model_name}."
#: apps/permission/signals.py:84 apps/permission/views.py:104 #: apps/permission/signals.py:85 apps/permission/views.py:104
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"You don't have the permission to add an instance of model {app_label}." "You don't have the permission to add an instance of model {app_label}."
@@ -2289,7 +2303,7 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}." "Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}."
"{model_name}." "{model_name}."
#: apps/permission/signals.py:113 #: apps/permission/signals.py:114
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"You don't have the permission to delete this instance of model {app_label}." "You don't have the permission to delete this instance of model {app_label}."
@@ -2377,7 +2391,7 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » " "Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » "
"avec ces paramètres. Merci de les corriger et de réessayer." "avec ces paramètres. Merci de les corriger et de réessayer."
#: apps/permission/views.py:111 note_kfet/templates/base.html:120 #: apps/permission/views.py:111 note_kfet/templates/base.html:121
msgid "Rights" msgid "Rights"
msgstr "Droits" msgstr "Droits"
@@ -2582,7 +2596,7 @@ msgstr ""
msgid "Invalidate pre-registration" msgid "Invalidate pre-registration"
msgstr "Invalider l'inscription" msgstr "Invalider l'inscription"
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:102 #: apps/treasury/apps.py:12 note_kfet/templates/base.html:103
msgid "Treasury" msgid "Treasury"
msgstr "Trésorerie" msgstr "Trésorerie"
@@ -2998,7 +3012,7 @@ msgstr "Gérer les crédits de la Société générale"
#: apps/wei/apps.py:10 apps/wei/models.py:42 apps/wei/models.py:43 #: apps/wei/apps.py:10 apps/wei/models.py:42 apps/wei/models.py:43
#: apps/wei/models.py:67 apps/wei/models.py:192 #: apps/wei/models.py:67 apps/wei/models.py:192
#: note_kfet/templates/base.html:108 #: note_kfet/templates/base.html:109
msgid "WEI" msgid "WEI"
msgstr "WEI" msgstr "WEI"
@@ -3753,7 +3767,7 @@ msgstr "données json"
msgid "data in the wrapped and generated by the script generate_wrapped" msgid "data in the wrapped and generated by the script generate_wrapped"
msgstr "donnée dans le wrapped et générée par le script generate_wrapped" msgstr "donnée dans le wrapped et générée par le script generate_wrapped"
#: apps/wrapped/models.py:70 note_kfet/templates/base.html:114 #: apps/wrapped/models.py:70 note_kfet/templates/base.html:115
msgid "Wrapped" msgid "Wrapped"
msgstr "Wrapped" msgstr "Wrapped"
@@ -3786,7 +3800,7 @@ msgid "Copy link"
msgstr "Copier le lien" msgstr "Copier le lien"
#: apps/wrapped/templates/wrapped/1/wrapped_base.html:16 #: apps/wrapped/templates/wrapped/1/wrapped_base.html:16
#: note_kfet/templates/base.html:14 #: note_kfet/templates/base.html:15
msgid "The ENS Paris-Saclay BDE note." msgid "The ENS Paris-Saclay BDE note."
msgstr "La note du BDE de l'ENS Paris-Saclay." msgstr "La note du BDE de l'ENS Paris-Saclay."
@@ -3908,19 +3922,19 @@ msgstr "Le wrapped est public"
msgid "List of wrapped" msgid "List of wrapped"
msgstr "Liste des wrapped" msgstr "Liste des wrapped"
#: note_kfet/settings/base.py:178 #: note_kfet/settings/base.py:180
msgid "German" msgid "German"
msgstr "Allemand" msgstr "Allemand"
#: note_kfet/settings/base.py:179 #: note_kfet/settings/base.py:181
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: note_kfet/settings/base.py:180 #: note_kfet/settings/base.py:182
msgid "Spanish" msgid "Spanish"
msgstr "Espagnol" msgstr "Espagnol"
#: note_kfet/settings/base.py:181 #: note_kfet/settings/base.py:183
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"
@@ -3981,34 +3995,34 @@ msgstr ""
msgid "Reset" msgid "Reset"
msgstr "Réinitialiser" msgstr "Réinitialiser"
#: note_kfet/templates/base.html:84 #: note_kfet/templates/base.html:85
msgid "Users" msgid "Users"
msgstr "Utilisateur·rices" msgstr "Utilisateur·rices"
#: note_kfet/templates/base.html:90 #: note_kfet/templates/base.html:91
msgid "Clubs" msgid "Clubs"
msgstr "Clubs" msgstr "Clubs"
#: note_kfet/templates/base.html:125 #: note_kfet/templates/base.html:126
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr "Admin"
#: note_kfet/templates/base.html:139 #: note_kfet/templates/base.html:140
msgid "My account" msgid "My account"
msgstr "Mon compte" msgstr "Mon compte"
#: note_kfet/templates/base.html:144 #: note_kfet/templates/base.html:145
msgid "Log out" msgid "Log out"
msgstr "Se déconnecter" msgstr "Se déconnecter"
#: note_kfet/templates/base.html:153 #: note_kfet/templates/base.html:154
#: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:6
#: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:11
#: note_kfet/templates/registration/signup.html:28 #: note_kfet/templates/registration/signup.html:28
msgid "Sign up" msgid "Sign up"
msgstr "Inscription" msgstr "Inscription"
#: note_kfet/templates/base.html:160 #: note_kfet/templates/base.html:161
#: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:6
#: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:15
#: note_kfet/templates/registration/login.html:38 #: note_kfet/templates/registration/login.html:38
@@ -4016,7 +4030,7 @@ msgstr "Inscription"
msgid "Log in" msgid "Log in"
msgstr "Se connecter" msgstr "Se connecter"
#: note_kfet/templates/base.html:174 #: note_kfet/templates/base.html:175
msgid "" msgid ""
"You are not a BDE member anymore. Please renew your membership if you want " "You are not a BDE member anymore. Please renew your membership if you want "
"to use the note." "to use the note."
@@ -4024,7 +4038,7 @@ msgstr ""
"Vous n'êtes plus adhérent·e BDE. Merci de réadhérer si vous voulez profiter " "Vous n'êtes plus adhérent·e BDE. Merci de réadhérer si vous voulez profiter "
"de la note." "de la note."
#: note_kfet/templates/base.html:180 #: note_kfet/templates/base.html:181
msgid "" msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click " "Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link." "on the validation link."
@@ -4032,7 +4046,7 @@ msgstr ""
"Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail " "Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail "
"et de cliquer sur le lien de validation." "et de cliquer sur le lien de validation."
#: note_kfet/templates/base.html:186 #: note_kfet/templates/base.html:187
msgid "" msgid ""
"You declared that you opened a bank account in the Société générale. The " "You declared that you opened a bank account in the Société générale. The "
"bank did not validate the creation of the account to the BDE, so the " "bank did not validate the creation of the account to the BDE, so the "
@@ -4046,30 +4060,38 @@ msgstr ""
"vérification peut durer quelques jours. Merci de vous assurer de bien aller " "vérification peut durer quelques jours. Merci de vous assurer de bien aller "
"au bout de vos démarches." "au bout de vos démarches."
#: note_kfet/templates/base.html:209 #: note_kfet/templates/base.html:214
msgid "Contact us" msgid "Contact us"
msgstr "Nous contacter" msgstr "Nous contacter"
#: note_kfet/templates/base.html:211 #: note_kfet/templates/base.html:216
msgid "Technical Support" msgid "Technical Support"
msgstr "Support technique" msgstr "Support technique"
#: note_kfet/templates/base.html:213 #: note_kfet/templates/base.html:218
msgid "Charte Info (FR)" msgid "Charte Info (FR)"
msgstr "Charte Info (FR)" msgstr "Charte Info (FR)"
#: note_kfet/templates/base.html:215 #: note_kfet/templates/base.html:220
msgid "FAQ (FR)" msgid "FAQ (FR)"
msgstr "FAQ (FR)" msgstr "FAQ (FR)"
#: note_kfet/templates/base.html:217 #: note_kfet/templates/base.html:222
msgid "Managed by BDE" msgid "Managed by BDE"
msgstr "Gérer par le BDE" msgstr "Gérer par le BDE"
#: note_kfet/templates/base.html:219 #: note_kfet/templates/base.html:224
msgid "Hosted by Cr@ns" msgid "Hosted by Cr@ns"
msgstr "Hébergé par le Cr@ans" msgstr "Hébergé par le Cr@ans"
#: note_kfet/templates/base.html:266
msgid "The note is not available for now"
msgstr "La note est indisponible pour le moment"
#: note_kfet/templates/base.html:268
msgid "Thank you for your understanding -- The Respos Info of BDE"
msgstr "Merci de votre compréhension -- Les Respos Info du BDE"
#: note_kfet/templates/base_search.html:15 #: note_kfet/templates/base_search.html:15
msgid "Search by attribute such as name..." msgid "Search by attribute such as name..."
msgstr "Chercher par un attribut tel que le nom..." msgstr "Chercher par un attribut tel que le nom..."
@@ -4078,6 +4100,41 @@ msgstr "Chercher par un attribut tel que le nom..."
msgid "There is no results." msgid "There is no results."
msgstr "Il n'y a pas de résultat." msgstr "Il n'y a pas de résultat."
#: note_kfet/templates/cas/logged.html:8
msgid ""
"<h3>Log In Successful</h3>You have successfully logged into the Central "
"Authentication Service.<br/>For security reasons, please Log Out and Exit "
"your web browser when you are done accessing services that require "
"authentication!"
msgstr ""
"<h3>Connection réussie</h3>Vous vous êtes bien connecté au Service Central d'Authentification."
"<br/>Pour des raisons de sécurité, veuillez vous déconnecter et fermer votre navigateur internet "
"une fois que vous aurez fini d'accéder aux services qui requiert une authentification !"
#: note_kfet/templates/cas/logged.html:14
msgid "Log me out from all my sessions"
msgstr "Me déconnecter de toutes mes sessions"
#: note_kfet/templates/cas/logged.html:20
msgid "Forget the identity provider"
msgstr "Oublier le fournisseur d'identité"
#: note_kfet/templates/cas/logged.html:24
msgid "Logout"
msgstr "Déconnexion"
#: note_kfet/templates/cas/login.html:11
msgid "Please log in"
msgstr "Veuillez vous connecter"
#: note_kfet/templates/cas/login.html:23
msgid "Login"
msgstr "Connexion"
#: note_kfet/templates/cas/warn.html:14
msgid "Connect to the service"
msgstr "Connexion au service"
#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8
msgid "Are you sure to delete the application" msgid "Are you sure to delete the application"
msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application" msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application"
@@ -4298,10 +4355,86 @@ msgstr ""
"d'adhésion. Vous devez également valider votre adresse email en suivant le " "d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu." "lien que vous avez reçu."
#, fuzzy, python-format #, fuzzy
#~| msgid "Creation date" #~| msgid "QR-code"
#~ msgid "Deposit %(name)s" #~ msgid "Go to QR-code"
#~ msgstr "Caution %(name)s" #~ msgstr "QR-code"
#, python-brace-format
#~ msgid "QR-code number {qr_code_number}"
#~ msgstr "Numéro du QR-code {qr_code_number}"
#~ msgid "was eaten"
#~ msgstr "a été mangé"
#~ msgid "is active"
#~ msgstr "est en cours"
#~ msgid "foods"
#~ msgstr "bouffes"
#~ msgid "Arrival date"
#~ msgstr "Date d'arrivée"
#~ msgid "Active"
#~ msgstr "Actif"
#~ msgid "Eaten"
#~ msgstr "Mangé"
#~ msgid "number"
#~ msgstr "numéro"
#~ msgid "View details"
#~ msgstr "Voir plus"
#~ msgid "Ready"
#~ msgstr "Prêt"
#~ msgid "Creation date"
#~ msgstr "Date de création"
#~ msgid "Ingredients"
#~ msgstr "Ingrédients"
#~ msgid "Open"
#~ msgstr "Open"
#~ msgid "All meals"
#~ msgstr "Tout les plats"
#~ msgid "There is no meal."
#~ msgstr "Il n'y a pas de plat"
#~ msgid "The product is already prepared"
#~ msgstr "Le produit est déjà prêt"
#~ msgid "Add a new basic food with QRCode"
#~ msgstr "Ajouter un nouvel ingrédient avec un QR-code"
#~ msgid "QRCode"
#~ msgstr "QR-code"
#~ msgid "Add a new meal"
#~ msgstr "Ajouter un nouveau plat"
#~ msgid "Update a meal"
#~ msgstr "Modifier le plat"
#, fuzzy
#~| msgid "invalidate"
#~ msgid "Enter a valid color."
#~ msgstr "dévalider"
#, fuzzy
#~| msgid "invalidate"
#~ msgid "Enter a valid value."
#~ msgstr "dévalider"
#, fuzzy
#~| msgid "Invitation"
#~ msgid "Syndication"
#~ msgstr "Invitation"
#, fuzzy #, fuzzy
#~| msgid "There is no results." #~| msgid "There is no results."
@@ -4715,7 +4848,7 @@ msgstr ""
#, python-brace-format #, python-brace-format
#~ msgid "QR-code number {qr_code_number}" #~ msgid "QR-code number {qr_code_number}"
#~ msgstr "numéro du QR-code {qr_code_number}" #~ msgstr "Numéro du QR-code {qr_code_number}"
#~ msgid "was eaten" #~ msgid "was eaten"
#~ msgstr "a été mangé" #~ msgstr "a été mangé"

View File

@@ -56,3 +56,8 @@ if "cas_server" in settings.INSTALLED_APPS:
from cas_server.models import * from cas_server.models import *
admin_site.register(ServicePattern, ServicePatternAdmin) admin_site.register(ServicePattern, ServicePatternAdmin)
admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin) admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin)
if "constance" in settings.INSTALLED_APPS:
from constance.admin import *
from constance.models import *
admin_site.register([Config], ConstanceAdmin)

View File

@@ -41,6 +41,7 @@ INSTALLED_APPS = [
'bootstrap_datepicker_plus', 'bootstrap_datepicker_plus',
'cas_server', 'cas_server',
'colorfield', 'colorfield',
'constance',
'crispy_bootstrap4', 'crispy_bootstrap4',
'crispy_forms', 'crispy_forms',
# 'django_htcpcp_tea', # 'django_htcpcp_tea',
@@ -112,6 +113,7 @@ TEMPLATES = [
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
'constance.context_processors.config',
'django.template.context_processors.debug', 'django.template.context_processors.debug',
'django.template.context_processors.request', 'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
@@ -308,6 +310,30 @@ PHONENUMBER_DEFAULT_REGION = 'FR'
# We add custom information to CAS, in order to give a normalized name to other services # We add custom information to CAS, in order to give a normalized name to other services
CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' CAS_AUTH_CLASS = 'member.auth.CustomAuthUser'
CAS_LOGIN_TEMPLATE = 'cas/login.html'
CAS_LOGOUT_TEMPLATE = 'cas/logout.html'
CAS_WARN_TEMPLATE = 'cas/warn.html'
CAS_LOGGED_TEMPLATE = 'cas/logged.html'
# Default field for primary key # Default field for primary key
DEFAULT_AUTO_FIELD = "django.db.models.AutoField" DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# Constance settings
CONSTANCE_ADDITIONAL_FIELDS = {
'banner_type': ['django.forms.fields.ChoiceField', {
'widget': 'django.forms.Select',
'choices': (('info', 'Info'), ('success', 'Success'), ('warning', 'Warning'), ('danger', 'Danger'))
}],
}
CONSTANCE_CONFIG = {
'BANNER_MESSAGE': ('', 'Some message', str),
'BANNER_TYPE': ('info', 'Banner type', 'banner_type'),
'MAINTENANCE': (False, 'check for mainteance mode', bool),
'MAINTENANCE_MESSAGE': ('', 'Some maintenance message', str),
}
CONSTANCE_CONFIG_FIELDSETS = {
'Maintenance': ('MAINTENANCE_MESSAGE', 'MAINTENANCE'),
'Banner': ('BANNER_MESSAGE', 'BANNER_TYPE'),
}
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
CONSTANCE_SUPERUSER_ONLY = True

View File

@@ -5,6 +5,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<!DOCTYPE html> <!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %} {% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %} class="position-relative h-100"> <html lang="{{ LANGUAGE_CODE|default:"en" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %} class="position-relative h-100">
{% if not config.MAINTENANCE %}
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -191,7 +192,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endblocktrans %} {% endblocktrans %}
</div> </div>
{% endif %} {% endif %}
{# TODO Add banners #} {% if config.BANNER_MESSAGE and user.is_authenticated %}
<div class="alert alert-{{ config.BANNER_TYPE }}">
{{ config.BANNER_MESSAGE }}
</div>
{% endif %}
</div> </div>
{% block content %} {% block content %}
<p>Default content...</p> <p>Default content...</p>
@@ -216,7 +221,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a href="https://bde.ens-cachan.fr" <a href="https://bde.ens-cachan.fr"
class="text-muted">{% trans "Managed by BDE" %}</a> &mdash; class="text-muted">{% trans "Managed by BDE" %}</a> &mdash;
<a href="https://crans.org" <a href="https://crans.org"
class="text-muted">{% trans "Hosted by Cr@ns" %}</a> &mdahs; class="text-muted">{% trans "Hosted by Cr@ns" %}</a> &mdash;
</span> </span>
{% csrf_token %} {% csrf_token %}
<select title="language" name="language" <select title="language" name="language"
@@ -253,4 +258,15 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block extrajavascript %}{% endblock %} {% block extrajavascript %}{% endblock %}
</body> </body>
{% endif %}
{% if config.MAINTENANCE %}
<body>
<div style="text-align:center">
<br />
{% trans "The note is not available for now" %}<br /><br />
{{ config.MAINTENANCE_MESSAGE }}<br /><br />
{% trans "Thank you for your understanding -- The Respos Info of BDE" %}
</div>
</body>
{% endif %}
</html> </html>

View File

@@ -0,0 +1,28 @@
{% extends "base.html" %}
{% comment %}
Copyright (C) by BDE ENS-Paris-Saclay
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n %}
{% block content %}
<div class="alert alert-success" role="alert">{% blocktrans %}<h3>Log In Successful</h3>You have successfully logged into the Central Authentication Service.<br/>For security reasons, please Log Out and Exit your web browser when you are done accessing services that require authentication!{% endblocktrans %}</div>
<div class="card bg-light mx-auto" style="max-width:30rem;">
<div class="card-body">
<form class="form-signin" method="get" action="logout">
<div class="checkbox">
<label>
<input type="checkbox" name="all" value="1">{% trans "Log me out from all my sessions" %}
</label>
</div>
{% if settings.CAS_FEDERATE and request.COOKIES.remember_provider %}
<div class="checkbox">
<label>
<input type="checkbox" name="forget_provider" value="1">{% trans "Forget the identity provider" %}
</label>
</div>
{% endif %}
<button class="btn btn-danger btn-block btn-lg" type="submit">{% trans "Logout" %}</button>
</form>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,42 @@
{% extends "base.html" %}
{% comment %}
Copyright (C) by BDE ENS-Paris-Saclay
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n %}
{% block ante_messages %}
{% if auto_submit %}<noscript>{% endif %}
<div class="card-header text-center">
<h2 class="form-signin-heading">{% trans "Please log in" %}</h2>
</div>
{% if auto_submit %}</noscript>{% endif %}
{% endblock %}
{% block content %}
<div class="card bg-light mx-auto" style="max-width: 30rem;">
<div class="card-body">
<form class="form-signin" method="post" id="login_form"{% if post_url %} action="{{post_url}}"{% endif %}>
{% csrf_token %}
{% include "cas_server/bs4/form.html" %}
{% if auto_submit %}<noscript>{% endif %}
<button class="btn btn-primary btn-block btn-lg" type="submit">{% trans "Login" %}</button>
{% if auto_submit %}</noscript>{% endif %}
</div>
</form>
</div>
</div>
{% endblock %}
{% block javascript_inline %}
jQuery(function( $ ){
$("#id_warn").click(function(e){
if($("#id_warn").is(':checked')){
createCookie("warn", "on", 10 * 365);
} else {
eraseCookie("warn");
}
});
});
{% if auto_submit %}document.getElementById('login_form').submit(); // SUBMIT FORM{% endif %}
{% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends "base.html" %}
{% comment %}
Copyright (C) by BDE ENS-Paris-Saclay
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n static %}
{% block content %}
<div class="alert alert-success" role="alert">{{ logout_msg }}</div>
{% endblock %}

View File

@@ -0,0 +1,19 @@
{% extends "base.html" %}
{% comment %}
Copyright (C) by BDE ENS-Paris-Saclay
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n static %}
{% block content %}
<div class="card bg-light mx-auto" style="max-width: 30rem;">
<div class="card-body">
<form class="form-signin" method="post">
{% csrf_token %}
{% include "cas_server/bs4/form.html" %}
<button class="btn btn-primary btn-block btn-lg" type="submit">{% trans "Connect to the service" %}</button>
</form>
</div>
</div>
{% endblock %}

View File

@@ -4,6 +4,7 @@ Django~=5.2.4
django-bootstrap-datepicker-plus~=5.0.5 django-bootstrap-datepicker-plus~=5.0.5
django-cas-server~=3.1.0 django-cas-server~=3.1.0
django-colorfield~=0.14.0 django-colorfield~=0.14.0
django-constance~=4.3.2
django-crispy-forms~=2.4.0 django-crispy-forms~=2.4.0
django-extensions>=4.1.0 django-extensions>=4.1.0
django-filter~=25.1 django-filter~=25.1