Compare commits

...

13 Commits

Author SHA1 Message Date
Yohann D'ANELLO ad2cc22964 Transactions are not invalidable if the user doesn't have the right to 2020-07-30 17:52:04 +02:00
Yohann D'ANELLO ae629b55ad Add HTML titles 2020-07-30 17:30:21 +02:00
Yohann D'ANELLO a5e50e5de6 Display true note name next to the alias, whenever the user has low permissions 2020-07-30 16:48:34 +02:00
Yohann D'ANELLO 9da8d49223 Remove ... when invalidating transaction 2020-07-30 16:41:41 +02:00
Yohann D'ANELLO aa66361ac7 Update permissions to create clubs.
For now, only superusers can edit the roles of a user.
2020-07-30 16:36:44 +02:00
Yohann D'ANELLO c14d37eaeb Fix deletion of consumptions in double consumption mode 2020-07-30 16:06:21 +02:00
Yohann D'ANELLO e9cbc8e623 Fix linters 2020-07-30 15:53:23 +02:00
Yohann D'ANELLO 9d8c588b78 Buttons list didn't work as well 2020-07-30 15:49:59 +02:00
Yohann D'ANELLO 484560fe4b Fix emitter button 2020-07-30 15:14:13 +02:00
Yohann D'ANELLO 9361f3f2f0 Aliases should load really faster 2020-07-30 15:07:30 +02:00
Yohann D'ANELLO e63219f7ad Force delete some objects 2020-07-30 14:58:18 +02:00
Yohann D'ANELLO 0c0aed0234 🐛 Force delete didn't work as well when trying to check add permissions 2020-07-30 13:10:03 +02:00
Yohann D'ANELLO fb775de923 Add backdoor to login as other users (in debug mode only) 2020-07-30 12:50:48 +02:00
38 changed files with 862 additions and 399 deletions

View File

@ -23,6 +23,7 @@ from .tables import ActivityTable, GuestTable, EntryTable
class ActivityCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
model = Activity
form_class = ActivityForm
extra_context = {"title": _("Create new activity")}
def form_valid(self, form):
form.instance.creater = self.request.user
@ -37,6 +38,7 @@ class ActivityListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView
model = Activity
table_class = ActivityTable
ordering = ('-date_start',)
extra_context = {"title": _("Activities")}
def get_queryset(self):
return super().get_queryset().distinct()
@ -44,8 +46,6 @@ class ActivityListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = _("Activities")
upcoming_activities = Activity.objects.filter(date_end__gt=datetime.now())
context['upcoming'] = ActivityTable(
data=upcoming_activities.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view")),
@ -58,6 +58,7 @@ class ActivityListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView
class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
model = Activity
context_object_name = "activity"
extra_context = {"title": _("Activity detail")}
def get_context_data(self, **kwargs):
context = super().get_context_data()
@ -74,6 +75,7 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
class ActivityUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
model = Activity
form_class = ActivityForm
extra_context = {"title": _("Update activity")}
def get_success_url(self, **kwargs):
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]})
@ -84,6 +86,12 @@ class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = GuestForm
template_name = "activity/activity_invite.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
activity = context["form"].activity
context["title"] = _('Invite guest to the activity "{}"').format(activity.name)
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.activity = Activity.objects.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view"))\

View File

@ -14,9 +14,11 @@ class ReadProtectedModelViewSet(viewsets.ModelViewSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
self.model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
def get_queryset(self):
user = get_current_authenticated_user()
self.queryset = model.objects.filter(PermissionBackend.filter_queryset(user, model, "view"))
return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view"))
class ReadOnlyProtectedModelViewSet(viewsets.ReadOnlyModelViewSet):
@ -26,6 +28,8 @@ class ReadOnlyProtectedModelViewSet(viewsets.ReadOnlyModelViewSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
self.model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
def get_queryset(self):
user = get_current_authenticated_user()
self.queryset = model.objects.filter(PermissionBackend.filter_queryset(user, model, "view"))
return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view"))

View File

@ -4,8 +4,8 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from note_kfet.admin import admin_site
from .forms import ProfileForm
from .models import Club, Membership, Profile

View File

@ -32,7 +32,6 @@ class UserForm(forms.ModelForm):
fields = ('first_name', 'last_name', 'username', 'email',)
class ProfileForm(forms.ModelForm):
"""
A form for the extras field provided by the :model:`member.Profile` model.

View File

@ -3,8 +3,10 @@
import hashlib
from django.conf import settings
from django.contrib.auth.hashers import PBKDF2PasswordHasher
from django.utils.crypto import constant_time_compare
from note_kfet.middlewares import get_current_authenticated_user, get_current_session
class CustomNK15Hasher(PBKDF2PasswordHasher):
@ -20,8 +22,37 @@ class CustomNK15Hasher(PBKDF2PasswordHasher):
"""
algorithm = "custom_nk15"
def must_update(self, encoded):
if settings.DEBUG:
current_user = get_current_authenticated_user()
if current_user is not None and current_user.is_superuser:
return False
return True
def verify(self, password, encoded):
if settings.DEBUG:
current_user = get_current_authenticated_user()
if current_user is not None and current_user.is_superuser\
and get_current_session().get("permission_mask", -1) >= 42:
return True
if '|' in encoded:
salt, db_hashed_pass = encoded.split('$')[2].split('|')
return constant_time_compare(hashlib.sha256((salt + password).encode("utf-8")).hexdigest(), db_hashed_pass)
return super().verify(password, encoded)
class DebugSuperuserBackdoor(PBKDF2PasswordHasher):
"""
In debug mode and during the beta, superusers can login into other accounts for tests.
"""
def must_update(self, encoded):
return False
def verify(self, password, encoded):
if settings.DEBUG:
current_user = get_current_authenticated_user()
if current_user is not None and current_user.is_superuser\
and get_current_session().get("permission_mask", -1) >= 42:
return True
return super().verify(password, encoded)

View File

@ -6,6 +6,7 @@ from datetime import datetime, timedelta
from PIL import Image
from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.auth.views import LoginView
@ -21,10 +22,10 @@ from note.forms import ImageForm
from note.models import Alias, NoteUser
from note.models.transactions import Transaction, SpecialTransaction
from note.tables import HistoryTable, AliasTable
from note_kfet.middlewares import _set_current_user_and_ip
from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin
from wei.models import WEIClub
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm
from .models import Club, Membership
@ -38,6 +39,8 @@ class CustomLoginView(LoginView):
form_class = CustomAuthenticationForm
def form_valid(self, form):
logout(self.request)
_set_current_user_and_ip(form.get_user(), self.request.session, None)
self.request.session['permission_mask'] = form.cleaned_data['permission_mask'].rank
return super().form_valid(form)
@ -50,6 +53,7 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
form_class = UserForm
template_name = 'member/profile_update.html'
context_object_name = 'user_object'
extra_context = {"title": _("Update Profile")}
profile_form = ProfileForm
@ -65,7 +69,6 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
form.fields['email'].help_text = _("This address must be valid.")
context['profile_form'] = self.profile_form(instance=context['user_object'].profile)
context['title'] = _("Update Profile")
return context
def form_valid(self, form):
@ -120,6 +123,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
model = User
context_object_name = "user_object"
template_name = "member/profile_detail.html"
extra_context = {"title": _("Profile detail")}
def get_queryset(self, **kwargs):
"""
@ -153,6 +157,7 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
model = User
table_class = UserTable
template_name = 'member/user_list.html'
extra_context = {"title": _("Search user")}
def get_queryset(self, **kwargs):
"""
@ -178,13 +183,6 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
return qs[:20]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["title"] = _("Search user")
return context
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
@ -193,6 +191,7 @@ class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
model = User
template_name = 'member/profile_alias.html'
context_object_name = 'user_object'
extra_context = {"title": _("Note aliases")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -206,6 +205,7 @@ class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, Det
Update profile picture of the user note.
"""
form_class = ImageForm
extra_context = {"title": _("Update note picture")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -263,6 +263,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
"""
model = Token
template_name = "member/manage_auth_tokens.html"
extra_context = {"title": _("Manage auth token")}
def get(self, request, *args, **kwargs):
if 'regenerate' in request.GET and Token.objects.filter(user=request.user).exists():
@ -290,6 +291,7 @@ class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
model = Club
form_class = ClubForm
success_url = reverse_lazy('member:club_list')
extra_context = {"title": _("Create new club")}
def form_valid(self, form):
return super().form_valid(form)
@ -301,6 +303,7 @@ class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
model = Club
table_class = ClubTable
extra_context = {"title": _("Search club")}
def get_queryset(self, **kwargs):
"""
@ -325,6 +328,7 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
model = Club
context_object_name = "club"
extra_context = {"title": _("Club detail")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -369,6 +373,7 @@ class ClubAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
model = Club
template_name = 'member/club_alias.html'
context_object_name = 'club'
extra_context = {"title": _("Note aliases")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -385,6 +390,7 @@ class ClubUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
context_object_name = "club"
form_class = ClubForm
template_name = "member/club_form.html"
extra_context = {"title": _("Update club")}
def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs)
@ -418,6 +424,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
model = Membership
form_class = MembershipForm
template_name = 'member/add_members.html'
extra_context = {"title": _("Add new member to the club")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -428,7 +435,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
.get(pk=self.kwargs["club_pk"], weiclub=None)
form.fields['credit_amount'].initial = club.membership_fee_paid
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not isinstance(club, WEIClub))
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub'))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
form.fields['roles'].initial = Role.objects.filter(name="Membre de club").all()
@ -449,7 +456,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
user = old_membership.user
form.fields['user'].initial = user
form.fields['user'].disabled = True
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not isinstance(club, WEIClub))
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub'))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
form.fields['roles'].initial = old_membership.roles.all()
form.fields['date_start'].initial = old_membership.date_end + timedelta(days=1)
@ -624,6 +631,7 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
model = Membership
form_class = MembershipForm
template_name = 'member/add_members.html'
extra_context = {"title": _("Manage roles of an user in the club")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -643,10 +651,10 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
del form.fields['bank']
club = self.object.club
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not isinstance(club, WEIClub))
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub'))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
return form
def get_success_url(self):
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.club.id})
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})

View File

@ -5,7 +5,6 @@ from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from polymorphic.admin import PolymorphicChildModelAdmin, \
PolymorphicChildModelFilter, PolymorphicParentModelAdmin
from note_kfet.admin import admin_site
from .models.notes import Alias, Note, NoteClub, NoteSpecial, NoteUser

View File

@ -119,7 +119,7 @@ class ConsumerSerializer(serializers.ModelSerializer):
# If the user has no right to see the note, then we only display the note identifier
if PermissionBackend.check_perm(get_current_authenticated_user(), "note.view_note", obj.note):
return NotePolymorphicSerializer().to_representation(obj.note)
return dict(id=obj.note.id)
return dict(id=obj.note.id, name=str(obj.note))
def get_email_confirmed(self, obj):
if isinstance(obj.note, NoteUser):

View File

@ -106,10 +106,8 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet):
queryset = super().get_queryset()
alias = self.request.query_params.get("alias", ".*")
queryset = queryset.filter(
Q(name__regex="^" + alias)
| Q(normalized_name__regex="^" + Alias.normalize(alias))
| Q(normalized_name__regex="^" + alias.lower())).order_by('name')
queryset = queryset.filter(normalized_name__iregex="^" + Alias.normalize(alias))\
.order_by('name').prefetch_related('note')
return queryset

View File

@ -8,6 +8,8 @@ from django.db.models import F
from django.utils.html import format_html
from django_tables2.utils import A
from django.utils.translation import gettext_lazy as _
from note_kfet.middlewares import get_current_authenticated_user
from permission.backends import PermissionBackend
from .models.notes import Alias
from .models.transactions import Transaction, TransactionTemplate
@ -52,14 +54,26 @@ class HistoryTable(tables.Table):
attrs={
"td": {
"id": lambda record: "validate_" + str(record.id),
"class": lambda record: str(record.valid).lower() + ' validate',
"class": lambda record:
str(record.valid).lower()
+ (' validate' if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason",
record) else ''),
"data-toggle": "tooltip",
"title": lambda record: _("Click to invalidate") if record.valid else _("Click to validate"),
"onclick": lambda record: 'de_validate(' + str(record.id) + ', ' + str(record.valid).lower() + ')',
"title": lambda record: (_("Click to invalidate") if record.valid else _("Click to validate"))
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
"onclick": lambda record: 'de_validate(' + str(record.id) + ', ' + str(record.valid).lower() + ')'
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
"onmouseover": lambda record: '$("#invalidity_reason_'
+ str(record.id) + '").show();$("#invalidity_reason_'
+ str(record.id) + '").focus();',
"onmouseout": lambda record: '$("#invalidity_reason_' + str(record.id) + '").hide()',
+ str(record.id) + '").focus();'
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
"onmouseout": lambda record: '$("#invalidity_reason_' + str(record.id) + '").hide()'
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
}
}
)
@ -88,6 +102,10 @@ class HistoryTable(tables.Table):
When the validation status is hovered, an input field is displayed to let the user specify an invalidity reason
"""
val = "" if value else ""
if not PermissionBackend\
.check_perm(get_current_authenticated_user(), "note.change_transaction_invalidity_reason", record):
return val
val += "<input type='text' class='form-control' id='invalidity_reason_" + str(record.id) \
+ "' value='" + (html.escape(record.invalidity_reason)
if record.invalidity_reason else ("" if value else str(_("No reason specified")))) \
@ -131,12 +149,10 @@ class ButtonTable(tables.Table):
row_attrs = {
'class': lambda record: 'table-row ' + ('table-success' if record.display else 'table-danger'),
'id': lambda record: "row-" + str(record.pk),
'data-href': lambda record: record.pk
}
model = TransactionTemplate
exclude = ('id',)
order_by = ('type', '-display', 'destination__name', 'name',)
edit = tables.LinkColumn('note:template_update',
args=[A('pk')],

View File

@ -5,6 +5,7 @@ import json
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView
from django_tables2 import SingleTableView
@ -29,6 +30,7 @@ class TransactionCreateView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTabl
model = Transaction
# Transaction history table
table_class = HistoryTable
extra_context = {"title": _("Transfer money")}
def get_queryset(self, **kwargs):
return super().get_queryset(**kwargs).order_by("-created_at").all()[:20]
@ -38,7 +40,6 @@ class TransactionCreateView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTabl
Add some context variables in template such as page title
"""
context = super().get_context_data(**kwargs)
context['title'] = _('Transfer money')
context['amount_widget'] = AmountInput(attrs={"id": "amount"})
context['polymorphic_ctype'] = ContentType.objects.get_for_model(Transaction).pk
context['special_polymorphic_ctype'] = ContentType.objects.get_for_model(SpecialTransaction).pk
@ -63,6 +64,7 @@ class TransactionTemplateCreateView(ProtectQuerysetMixin, LoginRequiredMixin, Cr
model = TransactionTemplate
form_class = TransactionTemplateForm
success_url = reverse_lazy('note:template_list')
extra_context = {"title": _("Create new button")}
class TransactionTemplateListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
@ -71,6 +73,20 @@ class TransactionTemplateListView(ProtectQuerysetMixin, LoginRequiredMixin, Sing
"""
model = TransactionTemplate
table_class = ButtonTable
extra_context = {"title": _("Search button")}
def get_queryset(self, **kwargs):
"""
Filter the user list with the given pattern.
"""
qs = super().get_queryset().distinct()
if "search" in self.request.GET:
pattern = self.request.GET["search"]
qs = qs.filter(Q(name__iregex="^" + pattern) | Q(destination__club__name__iregex="^" + pattern))
qs = qs.order_by('-display', 'category__name', 'destination__club__name', 'name')
return qs
class TransactionTemplateUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
@ -80,6 +96,7 @@ class TransactionTemplateUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, Up
model = TransactionTemplate
form_class = TransactionTemplateForm
success_url = reverse_lazy('note:template_list')
extra_context = {"title": _("Update button")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -116,6 +133,7 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
model = Transaction
template_name = "note/conso_form.html"
extra_context = {"title": _("Consumptions")}
# Transaction history table
table_class = HistoryTable
@ -137,7 +155,6 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
context['highlighted'] = TransactionTemplate.objects.filter(highlighted=True).filter(
PermissionBackend().filter_queryset(self.request.user, TransactionTemplate, "view")
).order_by('name').all()
context['title'] = _("Consumptions")
context['polymorphic_ctype'] = ContentType.objects.get_for_model(RecurrentTransaction).pk
# select2 compatibility

View File

@ -2,8 +2,8 @@
# SPDX-License-Identifier: GPL-3.0-or-lateré
from django.contrib import admin
from note_kfet.admin import admin_site
from .models import Permission, PermissionMask, Role

View File

@ -1,7 +1,6 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.contenttypes.models import ContentType
@ -50,7 +49,6 @@ class PermissionBackend(ModelBackend):
perms.append(perm)
return perms
@staticmethod
def permissions(user, model, type):
"""
@ -137,7 +135,7 @@ class PermissionBackend(ModelBackend):
if sess is not None and sess.session_key is None:
return False
if user_obj.is_superuser and get_current_session().get("permission_mask", -1) >= 42:
if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42:
return True
if obj is None:

View File

@ -4,6 +4,7 @@
from functools import lru_cache
from time import time
from django.conf import settings
from django.contrib.sessions.models import Session
from note_kfet.middlewares import get_current_session
@ -32,6 +33,10 @@ def memoize(f):
sess_funs = new_sess_funs
def func(*args, **kwargs):
if settings.DEBUG:
# Don't memoize in DEBUG mode
return f(*args, **kwargs)
nonlocal last_collect
if time() - last_collect > 60:

View File

@ -111,7 +111,7 @@
"note",
"alias"
],
"query": "[\"AND\", [\"OR\", {\"note__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__memberships__club__name\": \"Kfet\"}], [\"all\"]]}, {\"note__in\": [\"NoteClub\", \"objects\", [\"all\"]]}], {\"note__is_active\": true}]",
"query": "[\"AND\", [\"OR\", {\"note__noteuser__user__memberships__club__name\": \"Kfet\", \"note__noteuser__user__memberships__date_start__lte\": [\"today\"], \"note__noteuser__user__memberships__date_end__gte\": [\"today\"]}, {\"note__noteclub__isnull\": false}], {\"note__is_active\": true}]",
"type": "view",
"mask": 1,
"field": "",
@ -319,7 +319,7 @@
"note",
"note"
],
"query": "[\"OR\", {\"pk\": [\"club\", \"note\", \"pk\"]}, {\"pk__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__memberships__club\": [\"club\"]}], [\"all\"]]}]",
"query": "[\"OR\", {\"pk\": [\"club\", \"note\", \"pk\"]}, {\"noteuser__user__memberships__club\": [\"club\"], \"noteuser__user__memberships__date_start__lte\": [\"today\"], \"noteuser__user__memberships__date_end__gte\": [\"today\"]}]",
"type": "view",
"mask": 2,
"field": "",
@ -801,7 +801,7 @@
],
"query": "{\"club\": [\"club\"]}",
"type": "view",
"mask": 1,
"mask": 3,
"field": "",
"permanent": false,
"description": "View club's memberships"
@ -833,7 +833,7 @@
],
"query": "{\"club\": [\"club\"]}",
"type": "change",
"mask": 2,
"mask": 3,
"field": "roles",
"permanent": false,
"description": "Update user roles"
@ -2234,6 +2234,22 @@
{
"model": "permission.permission",
"pk": 139,
"fields": {
"model": [
"note",
"noteclub"
],
"query": "{}",
"type": "add",
"mask": 3,
"field": "",
"permanent": false,
"description": "Create any noteclub"
}
},
{
"model": "permission.permission",
"pk": 140,
"fields": {
"model": [
"member",
@ -2247,6 +2263,38 @@
"description": "Create any club"
}
},
{
"model": "permission.permission",
"pk": 141,
"fields": {
"model": [
"auth",
"user"
],
"query": "{\"memberships__club\": [\"club\"], \"memberships__date__start__lte\": [\"today\"], \"memberships__date__end__gte\": [\"today\"]}",
"type": "view",
"mask": 3,
"field": "",
"permanent": false,
"description": "View members of our club"
}
},
{
"model": "permission.permission",
"pk": 142,
"fields": {
"model": [
"note",
"noteclub"
],
"query": "{\"club\": [\"club\"]}",
"type": "view",
"mask": 2,
"field": "",
"permanent": false,
"description": "View club note"
}
},
{
"model": "permission.role",
"pk": 1,
@ -2323,7 +2371,8 @@
"permissions": [
22,
47,
49
49,
140
]
}
},
@ -2335,8 +2384,9 @@
"name": "Pr\u00e9sident\u00b7e de club",
"permissions": [
50,
51,
62
62,
141,
142
]
}
},
@ -2356,7 +2406,9 @@
61,
62,
127,
133
133,
141,
142
]
}
},
@ -2564,7 +2616,10 @@
136,
137,
138,
139
139,
140,
141,
142
]
}
},

View File

@ -44,7 +44,9 @@ class InstancedPermission:
else:
oldpk = obj.pk
# Ensure previous models are deleted
self.model.model_class().objects.filter(pk=obj.pk).annotate(_force_delete=F("pk")).delete()
for o in self.model.model_class().objects.filter(pk=obj.pk).all():
o._force_delete = True
Model.delete(o)
# Force insertion, no data verification, no trigger
obj._force_save = True
Model.save(obj, force_insert=True)

View File

@ -50,6 +50,7 @@ def pre_save_object(sender, instance, **kwargs):
# In the other case, we check if he/she has the right to change one field
previous = qs.get()
for field in instance._meta.fields:
field_name = field.name
old_value = getattr(previous, field.name)
@ -81,7 +82,8 @@ def pre_delete_object(instance, **kwargs):
if instance._meta.label_lower in EXCLUDED:
return
if hasattr(instance, "_force_delete"):
if hasattr(instance, "_force_delete") or hasattr(instance, "pk") and instance.pk == 0:
# Don't check permissions on force-deleted objects
return
user = get_current_authenticated_user()

View File

@ -41,6 +41,7 @@ class ProtectQuerysetMixin:
class RightsView(TemplateView):
template_name = "permission/all_rights.html"
extra_context = {"title": _("Rights")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

View File

@ -35,6 +35,7 @@ class UserCreateView(CreateView):
form_class = SignUpForm
template_name = 'registration/signup.html'
second_form = ProfileForm
extra_context = {"title": _("Register new user")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -78,6 +79,7 @@ class UserValidateView(TemplateView):
"""
title = _("Email validation")
template_name = 'registration/email_validation_complete.html'
extra_context = {"title": _("Validate a registration")}
def get(self, *args, **kwargs):
"""
@ -133,7 +135,7 @@ class UserValidationEmailSentView(TemplateView):
Display the information that the validation link has been sent.
"""
template_name = 'registration/email_validation_email_sent.html'
title = _('Email validation email sent')
extra_context = {"title": _('Email validation email sent')}
class UserResendValidationEmailView(LoginRequiredMixin, ProtectQuerysetMixin, DetailView):
@ -141,6 +143,7 @@ class UserResendValidationEmailView(LoginRequiredMixin, ProtectQuerysetMixin, De
Rensend the email validation link.
"""
model = User
extra_context = {"title": _("Resend email validation link")}
def get(self, request, *args, **kwargs):
user = self.get_object()
@ -158,6 +161,7 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
model = User
table_class = FutureUserTable
template_name = 'registration/future_user_list.html'
extra_context = {"title": _("Pre-registered users list")}
def get_queryset(self, **kwargs):
"""
@ -199,6 +203,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
form_class = ValidationForm
context_object_name = "user_object"
template_name = "registration/future_profile_detail.html"
extra_context = {"title": _("Registration detail")}
def post(self, request, *args, **kwargs):
form = self.get_form()
@ -355,6 +360,7 @@ class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View):
"""
Delete a pre-registered user.
"""
extra_context = {"title": _("Invalidate pre-registration")}
def get(self, request, *args, **kwargs):
"""

View File

@ -2,8 +2,8 @@
# SPDX-License-Identifier: GPL-3.0-or-lateré
from django.contrib import admin
from note_kfet.admin import admin_site
from .models import RemittanceType, Remittance, SogeCredit

View File

@ -15,6 +15,7 @@ from django.http import HttpResponse
from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView, DetailView
from django.views.generic.base import View, TemplateView
from django.views.generic.edit import BaseFormView
@ -35,6 +36,7 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = Invoice
form_class = InvoiceForm
extra_context = {"title": _("Create new invoice")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -77,6 +79,7 @@ class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView)
"""
model = Invoice
table_class = InvoiceTable
extra_context = {"title": _("Invoices list")}
class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
@ -85,6 +88,7 @@ class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
model = Invoice
form_class = InvoiceForm
extra_context = {"title": _("Update an invoice")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -167,7 +171,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
del tex
# The file has to be rendered twice
for _ in range(2):
for ignored in range(2):
error = subprocess.Popen(
["pdflatex", "invoice-{}.tex".format(pk)],
cwd=tmp_dir,
@ -198,6 +202,7 @@ class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView)
"""
model = Remittance
form_class = RemittanceForm
extra_context = {"title": _("Create a new remittance")}
def get_success_url(self):
return reverse_lazy('treasury:remittance_list')
@ -218,6 +223,7 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
List existing Remittances
"""
template_name = "treasury/remittance_list.html"
extra_context = {"title": _("Remittances list")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -267,6 +273,7 @@ class RemittanceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView)
"""
model = Remittance
form_class = RemittanceForm
extra_context = {"title": _("Update a remittance")}
def get_success_url(self):
return reverse_lazy('treasury:remittance_list')
@ -289,9 +296,9 @@ class LinkTransactionToRemittanceView(ProtectQuerysetMixin, LoginRequiredMixin,
"""
Attach a special transaction to a remittance
"""
model = SpecialTransactionProxy
form_class = LinkTransactionToRemittanceForm
extra_context = {"title": _("Attach a transaction to a remittance")}
def get_success_url(self):
return reverse_lazy('treasury:remittance_list')
@ -335,6 +342,7 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
"""
model = SogeCredit
table_class = SogeCreditTable
extra_context = {"title": _("List of credits from the Société générale")}
def get_queryset(self, **kwargs):
"""
@ -373,6 +381,7 @@ class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormVie
"""
model = SogeCredit
form_class = Form
extra_context = {"title": _("Manage credits from the Société générale")}
def form_valid(self, form):
if "validate" in form.data:

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from note_kfet.admin import admin_site
from .models import WEIClub, WEIRegistration, WEIMembership, WEIRole, Bus, BusTeam
admin_site.register(WEIClub)

View File

@ -52,6 +52,7 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
model = WEIClub
table_class = WEITable
ordering = '-year'
extra_context = {"title": _("Search WEI")}
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
@ -60,6 +61,7 @@ class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = WEIClub
form_class = WEIForm
extra_context = {"title": _("Create WEI")}
def form_valid(self, form):
form.instance.requires_membership = True
@ -79,6 +81,7 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
model = WEIClub
context_object_name = "club"
extra_context = {"title": _("WEI Detail")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -173,6 +176,7 @@ class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
"""
model = WEIMembership
table_class = WEIMembershipTable
extra_context = {"title": _("View members of the WEI")}
def dispatch(self, request, *args, **kwargs):
self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
@ -210,6 +214,7 @@ class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTable
"""
model = WEIRegistration
table_class = WEIRegistrationTable
extra_context = {"title": _("View registrations to the WEI")}
def dispatch(self, request, *args, **kwargs):
self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
@ -246,6 +251,7 @@ class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
model = WEIClub
context_object_name = "club"
form_class = WEIForm
extra_context = {"title": _("Update the WEI")}
def dispatch(self, request, *args, **kwargs):
wei = self.get_object()
@ -266,6 +272,7 @@ class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = Bus
form_class = BusForm
extra_context = {"title": _("Create new bus")}
def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["pk"])
@ -296,6 +303,7 @@ class BusUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
model = Bus
form_class = BusForm
extra_context = {"title": _("Update bus")}
def dispatch(self, request, *args, **kwargs):
wei = self.get_object().wei
@ -325,6 +333,7 @@ class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
Manage Bus
"""
model = Bus
extra_context = {"title": _("Manage bus")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -351,6 +360,7 @@ class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = BusTeam
form_class = BusTeamForm
extra_context = {"title": _("Create new team")}
def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"])
@ -382,6 +392,7 @@ class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
model = BusTeam
form_class = BusTeamForm
extra_context = {"title": _("Update team")}
def dispatch(self, request, *args, **kwargs):
wei = self.get_object().bus.wei
@ -412,6 +423,7 @@ class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
Manage Bus team
"""
model = BusTeam
extra_context = {"title": _("Manage WEI team")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -433,6 +445,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = WEIRegistration
form_class = WEIRegistrationForm
extra_context = {"title": _("Register first year student to the WEI")}
def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
@ -487,6 +500,7 @@ class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
model = WEIRegistration
form_class = WEIRegistrationForm
extra_context = {"title": _("Register old student to the WEI")}
def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
@ -564,6 +578,7 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
"""
model = WEIRegistration
form_class = WEIRegistrationForm
extra_context = {"title": _("Update WEI Registration")}
def get_queryset(self, **kwargs):
return WEIRegistration.objects
@ -653,6 +668,7 @@ class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Delete
Delete a non-validated WEI registration
"""
model = WEIRegistration
extra_context = {"title": _("Delete WEI registration")}
def dispatch(self, request, *args, **kwargs):
object = self.get_object()
@ -682,6 +698,7 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
"""
model = WEIMembership
form_class = WEIMembershipForm
extra_context = {"title": _("Validate WEI registration")}
def dispatch(self, request, *args, **kwargs):
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
@ -799,6 +816,7 @@ class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
model = WEIRegistration
template_name = "wei/survey.html"
survey = None
extra_context = {"title": _("Survey WEI")}
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
@ -836,7 +854,6 @@ class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = self.object.wei
context["title"] = _("Survey WEI")
return context
def form_valid(self, form):
@ -852,21 +869,21 @@ class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
class WEISurveyEndView(LoginRequiredMixin, TemplateView):
template_name = "wei/survey_end.html"
extra_context = {"title": _("Survey WEI")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
context["title"] = _("Survey WEI")
return context
class WEIClosedView(LoginRequiredMixin, TemplateView):
template_name = "wei/survey_closed.html"
extra_context = {"title": _("Survey WEI")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"])
context["title"] = _("Survey WEI")
return context

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-29 22:54+0200\n"
"POT-Creation-Date: 2020-07-30 17:22+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -46,7 +46,7 @@ msgstr ""
#: apps/activity/models.py:23 apps/activity/models.py:48
#: apps/member/models.py:151 apps/note/models/notes.py:188
#: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
#: apps/note/models/transactions.py:261 apps/permission/models.py:321
#: apps/note/models/transactions.py:261 apps/permission/models.py:323
#: apps/wei/models.py:65 apps/wei/models.py:117
#: templates/member/club_info.html:13 templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16
@ -71,14 +71,14 @@ msgid "activity types"
msgstr ""
#: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:102 apps/permission/models.py:181
#: apps/permission/models.py:104 apps/permission/models.py:183
#: apps/wei/models.py:71 apps/wei/models.py:128
#: templates/activity/activity_detail.html:16
msgid "description"
msgstr ""
#: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:66 apps/permission/models.py:156
#: apps/note/models/transactions.py:66 apps/permission/models.py:158
#: templates/activity/activity_detail.html:19
msgid "type"
msgstr ""
@ -186,12 +186,12 @@ msgstr ""
msgid "Type"
msgstr ""
#: apps/activity/tables.py:77 apps/member/forms.py:105
#: apps/activity/tables.py:77 apps/member/forms.py:104
#: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name"
msgstr ""
#: apps/activity/tables.py:79 apps/member/forms.py:110
#: apps/activity/tables.py:79 apps/member/forms.py:109
#: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126
msgid "First name"
@ -205,11 +205,27 @@ msgstr ""
msgid "Balance"
msgstr ""
#: apps/activity/views.py:47 templates/base.html:121
#: apps/activity/views.py:26
msgid "Create new activity"
msgstr ""
#: apps/activity/views.py:41 templates/base.html:121
msgid "Activities"
msgstr ""
#: apps/activity/views.py:163
#: apps/activity/views.py:61
msgid "Activity detail"
msgstr ""
#: apps/activity/views.py:78
msgid "Update activity"
msgstr ""
#: apps/activity/views.py:92
msgid "Invite guest to the activity \"{}\""
msgstr ""
#: apps/activity/views.py:171
msgid "Entry for activity \"{}\""
msgstr ""
@ -225,7 +241,7 @@ msgstr ""
msgid "IP Address"
msgstr ""
#: apps/logs/models.py:35 apps/permission/models.py:126
#: apps/logs/models.py:35 apps/permission/models.py:128
msgid "model"
msgstr ""
@ -245,12 +261,12 @@ msgstr ""
msgid "create"
msgstr ""
#: apps/logs/models.py:61 apps/note/tables.py:145
#: apps/logs/models.py:61 apps/note/tables.py:143
#: templates/activity/activity_detail.html:67
msgid "edit"
msgstr ""
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:150
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:148
#: apps/wei/tables.py:65
msgid "delete"
msgstr ""
@ -279,35 +295,35 @@ msgstr ""
msgid "member"
msgstr ""
#: apps/member/forms.py:59 apps/member/views.py:78
#: apps/member/forms.py:58 apps/member/views.py:81
msgid "An alias with a similar name already exists."
msgstr ""
#: apps/member/forms.py:84 apps/registration/forms.py:44
#: apps/member/forms.py:83 apps/registration/forms.py:44
msgid "Inscription paid by Société Générale"
msgstr ""
#: apps/member/forms.py:86 apps/registration/forms.py:46
#: apps/member/forms.py:85 apps/registration/forms.py:46
msgid "Check this case is the Société Générale paid the inscription."
msgstr ""
#: apps/member/forms.py:91 apps/registration/forms.py:51
#: apps/member/forms.py:90 apps/registration/forms.py:51
msgid "Credit type"
msgstr ""
#: apps/member/forms.py:92 apps/registration/forms.py:52
#: apps/member/forms.py:91 apps/registration/forms.py:52
msgid "No credit"
msgstr ""
#: apps/member/forms.py:94
#: apps/member/forms.py:93
msgid "You can credit the note of the user."
msgstr ""
#: apps/member/forms.py:98 apps/registration/forms.py:57
#: apps/member/forms.py:97 apps/registration/forms.py:57
msgid "Credit amount"
msgstr ""
#: apps/member/forms.py:115 apps/registration/forms.py:74
#: apps/member/forms.py:114 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank"
msgstr ""
@ -509,7 +525,7 @@ msgstr ""
msgid "fee"
msgstr ""
#: apps/member/models.py:303 apps/member/views.py:528 apps/wei/views.py:770
#: apps/member/models.py:303 apps/member/views.py:535 apps/wei/views.py:787
msgid "User is not a member of the parent club"
msgstr ""
@ -518,7 +534,7 @@ msgstr ""
msgid "The role {role} does not apply to the club {club}."
msgstr ""
#: apps/member/models.py:321 apps/member/views.py:537
#: apps/member/models.py:321 apps/member/views.py:544
msgid "User is already a member of the club"
msgstr ""
@ -539,45 +555,85 @@ msgstr ""
msgid "Renew"
msgstr ""
#: apps/member/views.py:65 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr ""
#: apps/member/views.py:68 templates/member/profile_info.html:47
#: apps/member/views.py:56 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:130
msgid "Update Profile"
msgstr ""
#: apps/member/views.py:184
#: apps/member/views.py:69 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr ""
#: apps/member/views.py:126
msgid "Profile detail"
msgstr ""
#: apps/member/views.py:160
msgid "Search user"
msgstr ""
#: apps/member/views.py:523 apps/wei/views.py:761
#: apps/member/views.py:194 apps/member/views.py:376
msgid "Note aliases"
msgstr ""
#: apps/member/views.py:208
msgid "Update note picture"
msgstr ""
#: apps/member/views.py:266 templates/member/profile_info.html:43
msgid "Manage auth token"
msgstr ""
#: apps/member/views.py:294
msgid "Create new club"
msgstr ""
#: apps/member/views.py:306
msgid "Search club"
msgstr ""
#: apps/member/views.py:331
msgid "Club detail"
msgstr ""
#: apps/member/views.py:393
msgid "Update club"
msgstr ""
#: apps/member/views.py:427
msgid "Add new member to the club"
msgstr ""
#: apps/member/views.py:530 apps/wei/views.py:778
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
msgstr ""
#: apps/member/views.py:541
#: apps/member/views.py:548
msgid "The membership must start after {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:546
#: apps/member/views.py:553
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:563 apps/member/views.py:565 apps/member/views.py:567
#: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:294
#: apps/member/views.py:570 apps/member/views.py:572 apps/member/views.py:574
#: apps/registration/views.py:295 apps/registration/views.py:297
#: apps/registration/views.py:299
msgid "This field is required."
msgstr ""
#: apps/note/admin.py:122 apps/note/models/transactions.py:106
#: apps/member/views.py:634
msgid "Manage roles of an user in the club"
msgstr ""
#: apps/note/admin.py:121 apps/note/models/transactions.py:106
msgid "source"
msgstr ""
#: apps/note/admin.py:130 apps/note/admin.py:172
#: apps/note/admin.py:129 apps/note/admin.py:171
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr ""
@ -814,113 +870,129 @@ msgstr ""
msgid "No reason specified"
msgstr ""
#: apps/note/tables.py:122 apps/note/tables.py:152 apps/wei/tables.py:66
#: apps/note/tables.py:122 apps/note/tables.py:150 apps/wei/tables.py:66
#: templates/treasury/sogecredit_detail.html:59
#: templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete"
msgstr ""
#: apps/note/tables.py:147 apps/wei/tables.py:42 apps/wei/tables.py:43
#: apps/note/tables.py:145 apps/wei/tables.py:42 apps/wei/tables.py:43
#: templates/member/club_info.html:67 templates/note/conso_form.html:128
#: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
#: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
msgid "Edit"
msgstr ""
#: apps/note/views.py:41
#: apps/note/views.py:33
msgid "Transfer money"
msgstr ""
#: apps/note/views.py:140 templates/base.html:94
msgid "Consumptions"
#: apps/note/views.py:67
msgid "Create new button"
msgstr ""
#: apps/permission/models.py:81
#, python-brace-format
msgid "Can {type} {model}.{field} in {query}"
#: apps/note/views.py:76
msgid "Search button"
msgstr ""
#: apps/note/views.py:99
msgid "Update button"
msgstr ""
#: apps/note/views.py:136 templates/base.html:94
msgid "Consumptions"
msgstr ""
#: apps/permission/models.py:83
#, python-brace-format
msgid "Can {type} {model}.{field} in {query}"
msgstr ""
#: apps/permission/models.py:85
#, python-brace-format
msgid "Can {type} {model} in {query}"
msgstr ""
#: apps/permission/models.py:96
#: apps/permission/models.py:98
msgid "rank"
msgstr ""
#: apps/permission/models.py:109
#: apps/permission/models.py:111
msgid "permission mask"
msgstr ""
#: apps/permission/models.py:110
#: apps/permission/models.py:112
msgid "permission masks"
msgstr ""
#: apps/permission/models.py:150
#: apps/permission/models.py:152
msgid "query"
msgstr ""
#: apps/permission/models.py:163
#: apps/permission/models.py:165
msgid "mask"
msgstr ""
#: apps/permission/models.py:169
#: apps/permission/models.py:171
msgid "field"
msgstr ""
#: apps/permission/models.py:174
#: apps/permission/models.py:176
msgid ""
"Tells if the permission should be granted even if the membership of the user "
"is expired."
msgstr ""
#: apps/permission/models.py:175 templates/permission/all_rights.html:26
#: apps/permission/models.py:177 templates/permission/all_rights.html:26
msgid "permanent"
msgstr ""
#: apps/permission/models.py:186
#: apps/permission/models.py:188
msgid "permission"
msgstr ""
#: apps/permission/models.py:187 apps/permission/models.py:326
#: apps/permission/models.py:189 apps/permission/models.py:328
msgid "permissions"
msgstr ""
#: apps/permission/models.py:192
#: apps/permission/models.py:194
msgid "Specifying field applies only to view and change permission types."
msgstr ""
#: apps/permission/models.py:331
#: apps/permission/models.py:333
msgid "for club"
msgstr ""
#: apps/permission/models.py:341 apps/permission/models.py:342
#: apps/permission/models.py:343 apps/permission/models.py:344
msgid "role permissions"
msgstr ""
#: apps/permission/signals.py:62
#: apps/permission/signals.py:63
#, python-brace-format
msgid ""
"You don't have the permission to change the field {field} on this instance "
"of model {app_label}.{model_name}."
msgstr ""
#: apps/permission/signals.py:72
#: apps/permission/signals.py:73
#, python-brace-format
msgid ""
"You don't have the permission to add this instance of model {app_label}."
"{model_name}."
msgstr ""
#: apps/permission/signals.py:99
#: apps/permission/signals.py:101
#, python-brace-format
msgid ""
"You don't have the permission to delete this instance of model {app_label}."
"{model_name}."
msgstr ""
#: apps/permission/views.py:48
#: apps/permission/views.py:44 templates/base.html:135
msgid "Rights"
msgstr ""
#: apps/permission/views.py:49
msgid "All rights"
msgstr ""
@ -946,35 +1018,59 @@ msgstr ""
msgid "Join Kfet Club"
msgstr ""
#: apps/registration/views.py:79
#: apps/registration/views.py:38
msgid "Register new user"
msgstr ""
#: apps/registration/views.py:80
msgid "Email validation"
msgstr ""
#: apps/registration/views.py:125
#: apps/registration/views.py:82
msgid "Validate a registration"
msgstr ""
#: apps/registration/views.py:127
msgid "Email validation unsuccessful"
msgstr ""
#: apps/registration/views.py:136
#: apps/registration/views.py:138
msgid "Email validation email sent"
msgstr ""
#: apps/registration/views.py:189
#: apps/registration/views.py:146
msgid "Resend email validation link"
msgstr ""
#: apps/registration/views.py:164
msgid "Pre-registered users list"
msgstr ""
#: apps/registration/views.py:193
msgid "Unregistered users"
msgstr ""
#: apps/registration/views.py:256
#: apps/registration/views.py:206
msgid "Registration detail"
msgstr ""
#: apps/registration/views.py:261
msgid "You must join the BDE."
msgstr ""
#: apps/registration/views.py:278
#: apps/registration/views.py:283
msgid "You must join BDE club before joining Kfet club."
msgstr ""
#: apps/registration/views.py:283
#: apps/registration/views.py:288
msgid ""
"The entered amount is not enough for the memberships, should be at least {}"
msgstr ""
#: apps/registration/views.py:363
msgid "Invalidate pre-registration"
msgstr ""
#: apps/treasury/apps.py:12 templates/base.html:126
msgid "Treasury"
msgstr ""
@ -1172,6 +1268,43 @@ msgstr ""
msgid "No"
msgstr ""
#: apps/treasury/views.py:39
msgid "Create new invoice"
msgstr ""
#: apps/treasury/views.py:82 templates/treasury/invoice_form.html:6
msgid "Invoices list"
msgstr ""
#: apps/treasury/views.py:91
msgid "Update an invoice"
msgstr ""
#: apps/treasury/views.py:205
msgid "Create a new remittance"
msgstr ""
#: apps/treasury/views.py:226 templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr ""
#: apps/treasury/views.py:276
msgid "Update a remittance"
msgstr ""
#: apps/treasury/views.py:301
msgid "Attach a transaction to a remittance"
msgstr ""
#: apps/treasury/views.py:345
msgid "List of credits from the Société générale"
msgstr ""
#: apps/treasury/views.py:384
msgid "Manage credits from the Société générale"
msgstr ""
#: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
#: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:131
msgid "WEI"
@ -1389,45 +1522,113 @@ msgstr ""
msgid "members"
msgstr ""
#: apps/wei/views.py:203
#: apps/wei/views.py:55
msgid "Search WEI"
msgstr ""
#: apps/wei/views.py:64 templates/wei/weiclub_list.html:9
msgid "Create WEI"
msgstr ""
#: apps/wei/views.py:84
msgid "WEI Detail"
msgstr ""
#: apps/wei/views.py:179
msgid "View members of the WEI"
msgstr ""
#: apps/wei/views.py:207
msgid "Find WEI Membership"
msgstr ""
#: apps/wei/views.py:238
#: apps/wei/views.py:217
msgid "View registrations to the WEI"
msgstr ""
#: apps/wei/views.py:243
msgid "Find WEI Registration"
msgstr ""
#: apps/wei/views.py:447 templates/wei/weiclub_info.html:62
#: apps/wei/views.py:254
msgid "Update the WEI"
msgstr ""
#: apps/wei/views.py:275
msgid "Create new bus"
msgstr ""
#: apps/wei/views.py:306
msgid "Update bus"
msgstr ""
#: apps/wei/views.py:336
msgid "Manage bus"
msgstr ""
#: apps/wei/views.py:363
msgid "Create new team"
msgstr ""
#: apps/wei/views.py:395
msgid "Update team"
msgstr ""
#: apps/wei/views.py:426
msgid "Manage WEI team"
msgstr ""
#: apps/wei/views.py:448
msgid "Register first year student to the WEI"
msgstr ""
#: apps/wei/views.py:460 templates/wei/weiclub_info.html:62
msgid "Register 1A"
msgstr ""
#: apps/wei/views.py:468 apps/wei/views.py:537
#: apps/wei/views.py:481 apps/wei/views.py:551
msgid "This user is already registered to this WEI."
msgstr ""
#: apps/wei/views.py:473
#: apps/wei/views.py:486
msgid ""
"This user can't be in her/his first year since he/she has already participed "
"to a WEI."
msgstr ""
#: apps/wei/views.py:501 templates/wei/weiclub_info.html:65
#: apps/wei/views.py:503
msgid "Register old student to the WEI"
msgstr ""
#: apps/wei/views.py:515 templates/wei/weiclub_info.html:65
msgid "Register 2A+"
msgstr ""
#: apps/wei/views.py:519 apps/wei/views.py:606
#: apps/wei/views.py:533 apps/wei/views.py:621
msgid "You already opened an account in the Société générale."
msgstr ""
#: apps/wei/views.py:666
#: apps/wei/views.py:581
msgid "Update WEI Registration"
msgstr ""
#: apps/wei/views.py:671
msgid "Delete WEI registration"
msgstr ""
#: apps/wei/views.py:682
msgid "You don't have the right to delete this WEI registration."
msgstr ""
#: apps/wei/views.py:765
#: apps/wei/views.py:701
msgid "Validate WEI registration"
msgstr ""
#: apps/wei/views.py:782
msgid "This user didn't give her/his caution check."
msgstr ""
#: apps/wei/views.py:839 apps/wei/views.py:859 apps/wei/views.py:869
#: apps/wei/views.py:819 apps/wei/views.py:872 apps/wei/views.py:882
#: templates/wei/survey.html:12 templates/wei/survey_closed.html:12
#: templates/wei/survey_end.html:12
msgid "Survey WEI"
@ -1562,10 +1763,6 @@ msgstr ""
msgid "Registrations"
msgstr ""
#: templates/base.html:135
msgid "Rights"
msgstr ""
#: templates/base.html:139
msgid "Administration"
msgstr ""
@ -1623,15 +1820,11 @@ msgstr ""
msgid "View Profile"
msgstr ""
#: templates/member/club_list.html:8
msgid "search clubs"
msgstr ""
#: templates/member/club_list.html:12
#: templates/member/club_list.html:9
msgid "Create club"
msgstr ""
#: templates/member/club_list.html:19
#: templates/member/club_list.html:16
msgid "Club listing"
msgstr ""
@ -1675,10 +1868,6 @@ msgstr ""
msgid "Change password"
msgstr ""
#: templates/member/profile_info.html:43
msgid "Manage auth token"
msgstr ""
#: templates/member/profile_tables.html:7
#: templates/registration/future_profile_detail.html:28
#: templates/wei/weimembership_form.html:30
@ -1776,31 +1965,23 @@ msgstr ""
msgid "Current price"
msgstr ""
#: templates/note/transactiontemplate_list.html:9
msgid "Search button"
msgstr ""
#: templates/note/transactiontemplate_list.html:11
#: templates/note/transactiontemplate_list.html:8
msgid "Name of the button..."
msgstr ""
#: templates/note/transactiontemplate_list.html:16
msgid "Display visible buttons only"
msgstr ""
#: templates/note/transactiontemplate_list.html:21
#: templates/note/transactiontemplate_list.html:10
msgid "New button"
msgstr ""
#: templates/note/transactiontemplate_list.html:28
#: templates/note/transactiontemplate_list.html:17
msgid "buttons listing "
msgstr ""
#: templates/note/transactiontemplate_list.html:86
#: templates/note/transactiontemplate_list.html:55
msgid "button successfully deleted "
msgstr ""
#: templates/note/transactiontemplate_list.html:90
#: templates/note/transactiontemplate_list.html:59
msgid "Unable to delete button "
msgstr ""
@ -1985,10 +2166,6 @@ msgid ""
"by following the link you received."
msgstr ""
#: templates/treasury/invoice_form.html:6
msgid "Invoices list"
msgstr ""
#: templates/treasury/invoice_form.html:41
msgid "Add product"
msgstr ""
@ -2011,11 +2188,6 @@ msgstr ""
msgid "Remittance #"
msgstr ""
#: templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr ""
#: templates/treasury/remittance_form.html:12
msgid "Count"
msgstr ""
@ -2165,15 +2337,7 @@ msgstr ""
msgid "View WEI"
msgstr ""
#: templates/wei/weiclub_list.html:8
msgid "search WEI"
msgstr ""
#: templates/wei/weiclub_list.html:12
msgid "Create WEI"
msgstr ""
#: templates/wei/weiclub_list.html:19
#: templates/wei/weiclub_list.html:16
msgid "WEI listing"
msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-29 22:54+0200\n"
"POT-Creation-Date: 2020-07-30 17:22+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -47,7 +47,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/activity/models.py:23 apps/activity/models.py:48
#: apps/member/models.py:151 apps/note/models/notes.py:188
#: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
#: apps/note/models/transactions.py:261 apps/permission/models.py:321
#: apps/note/models/transactions.py:261 apps/permission/models.py:323
#: apps/wei/models.py:65 apps/wei/models.py:117
#: templates/member/club_info.html:13 templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16
@ -72,14 +72,14 @@ msgid "activity types"
msgstr "types d'activité"
#: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:102 apps/permission/models.py:181
#: apps/permission/models.py:104 apps/permission/models.py:183
#: apps/wei/models.py:71 apps/wei/models.py:128
#: templates/activity/activity_detail.html:16
msgid "description"
msgstr "description"
#: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:66 apps/permission/models.py:156
#: apps/note/models/transactions.py:66 apps/permission/models.py:158
#: templates/activity/activity_detail.html:19
msgid "type"
msgstr "type"
@ -187,12 +187,12 @@ msgstr "supprimer"
msgid "Type"
msgstr "Type"
#: apps/activity/tables.py:77 apps/member/forms.py:105
#: apps/activity/tables.py:77 apps/member/forms.py:104
#: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name"
msgstr "Nom de famille"
#: apps/activity/tables.py:79 apps/member/forms.py:110
#: apps/activity/tables.py:79 apps/member/forms.py:109
#: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126
msgid "First name"
@ -206,11 +206,27 @@ msgstr "Note"
msgid "Balance"
msgstr "Solde du compte"
#: apps/activity/views.py:47 templates/base.html:121
#: apps/activity/views.py:26
msgid "Create new activity"
msgstr "Créer une nouvelle activité"
#: apps/activity/views.py:41 templates/base.html:121
msgid "Activities"
msgstr "Activités"
#: apps/activity/views.py:163
#: apps/activity/views.py:61
msgid "Activity detail"
msgstr "Détails de l'activité"
#: apps/activity/views.py:78
msgid "Update activity"
msgstr "Modifier l'activité"
#: apps/activity/views.py:92
msgid "Invite guest to the activity \"{}\""
msgstr "Invitation pour l'activité « {} »"
#: apps/activity/views.py:171
msgid "Entry for activity \"{}\""
msgstr "Entrées pour l'activité « {} »"
@ -226,7 +242,7 @@ msgstr "Logs"
msgid "IP Address"
msgstr "Adresse IP"
#: apps/logs/models.py:35 apps/permission/models.py:126
#: apps/logs/models.py:35 apps/permission/models.py:128
msgid "model"
msgstr "Modèle"
@ -246,12 +262,12 @@ msgstr "Nouvelles données"
msgid "create"
msgstr "Créer"
#: apps/logs/models.py:61 apps/note/tables.py:145
#: apps/logs/models.py:61 apps/note/tables.py:143
#: templates/activity/activity_detail.html:67
msgid "edit"
msgstr "Modifier"
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:150
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:148
#: apps/wei/tables.py:65
msgid "delete"
msgstr "Supprimer"
@ -280,35 +296,35 @@ msgstr "journaux de modifications"
msgid "member"
msgstr "adhérent"
#: apps/member/forms.py:59 apps/member/views.py:78
#: apps/member/forms.py:58 apps/member/views.py:81
msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà."
#: apps/member/forms.py:84 apps/registration/forms.py:44
#: apps/member/forms.py:83 apps/registration/forms.py:44
msgid "Inscription paid by Société Générale"
msgstr "Inscription payée par la Société générale"
#: apps/member/forms.py:86 apps/registration/forms.py:46
#: apps/member/forms.py:85 apps/registration/forms.py:46
msgid "Check this case is the Société Générale paid the inscription."
msgstr "Cochez cette case si la Société Générale a payé l'inscription."
#: apps/member/forms.py:91 apps/registration/forms.py:51
#: apps/member/forms.py:90 apps/registration/forms.py:51
msgid "Credit type"
msgstr "Type de rechargement"
#: apps/member/forms.py:92 apps/registration/forms.py:52
#: apps/member/forms.py:91 apps/registration/forms.py:52
msgid "No credit"
msgstr "Pas de rechargement"
#: apps/member/forms.py:94
#: apps/member/forms.py:93
msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion."
#: apps/member/forms.py:98 apps/registration/forms.py:57
#: apps/member/forms.py:97 apps/registration/forms.py:57
msgid "Credit amount"
msgstr "Montant à créditer"
#: apps/member/forms.py:115 apps/registration/forms.py:74
#: apps/member/forms.py:114 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank"
msgstr "Banque"
@ -514,7 +530,7 @@ msgstr "l'adhésion finit le"
msgid "fee"
msgstr "cotisation"
#: apps/member/models.py:303 apps/member/views.py:528 apps/wei/views.py:770
#: apps/member/models.py:303 apps/member/views.py:535 apps/wei/views.py:787
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
@ -523,7 +539,7 @@ msgstr "L'utilisateur n'est pas membre du club parent"
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:321 apps/member/views.py:537
#: apps/member/models.py:321 apps/member/views.py:544
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
@ -544,21 +560,57 @@ msgstr "adhésions"
msgid "Renew"
msgstr "Renouveler"
#: apps/member/views.py:65 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr "Cette adresse doit être valide."
#: apps/member/views.py:68 templates/member/profile_info.html:47
#: apps/member/views.py:56 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:130
msgid "Update Profile"
msgstr "Modifier le profil"
#: apps/member/views.py:184
#: apps/member/views.py:69 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr "Cette adresse doit être valide."
#: apps/member/views.py:126
msgid "Profile detail"
msgstr "Détails de l'utilisateur"
#: apps/member/views.py:160
msgid "Search user"
msgstr "Chercher un utilisateur"
#: apps/member/views.py:523 apps/wei/views.py:761
#: apps/member/views.py:194 apps/member/views.py:376
msgid "Note aliases"
msgstr "Alias de la note"
#: apps/member/views.py:208
msgid "Update note picture"
msgstr "Modifier la photo de la note"
#: apps/member/views.py:266 templates/member/profile_info.html:43
msgid "Manage auth token"
msgstr "Gérer les jetons d'authentification"
#: apps/member/views.py:294
msgid "Create new club"
msgstr "Créer un nouveau club"
#: apps/member/views.py:306
msgid "Search club"
msgstr "Chercher un club"
#: apps/member/views.py:331
msgid "Club detail"
msgstr "Détails du club"
#: apps/member/views.py:393
msgid "Update club"
msgstr "Modifier le club"
#: apps/member/views.py:427
msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club"
#: apps/member/views.py:530 apps/wei/views.py:778
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@ -566,25 +618,29 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif."
#: apps/member/views.py:541
#: apps/member/views.py:548
msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
#: apps/member/views.py:546
#: apps/member/views.py:553
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:563 apps/member/views.py:565 apps/member/views.py:567
#: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:294
#: apps/member/views.py:570 apps/member/views.py:572 apps/member/views.py:574
#: apps/registration/views.py:295 apps/registration/views.py:297
#: apps/registration/views.py:299
msgid "This field is required."
msgstr "Ce champ est requis."
#: apps/note/admin.py:122 apps/note/models/transactions.py:106
#: apps/member/views.py:634
msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club"
#: apps/note/admin.py:121 apps/note/models/transactions.py:106
msgid "source"
msgstr "source"
#: apps/note/admin.py:130 apps/note/admin.py:172
#: apps/note/admin.py:129 apps/note/admin.py:171
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr "destination"
@ -826,62 +882,74 @@ msgstr "Cliquez pour valider"
msgid "No reason specified"
msgstr "Pas de motif spécifié"
#: apps/note/tables.py:122 apps/note/tables.py:152 apps/wei/tables.py:66
#: apps/note/tables.py:122 apps/note/tables.py:150 apps/wei/tables.py:66
#: templates/treasury/sogecredit_detail.html:59
#: templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete"
msgstr "Supprimer"
#: apps/note/tables.py:147 apps/wei/tables.py:42 apps/wei/tables.py:43
#: apps/note/tables.py:145 apps/wei/tables.py:42 apps/wei/tables.py:43
#: templates/member/club_info.html:67 templates/note/conso_form.html:128
#: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
#: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
msgid "Edit"
msgstr "Éditer"
#: apps/note/views.py:41
#: apps/note/views.py:33
msgid "Transfer money"
msgstr "Transférer de l'argent"
#: apps/note/views.py:140 templates/base.html:94
#: apps/note/views.py:67
msgid "Create new button"
msgstr "Créer un nouveau bouton"
#: apps/note/views.py:76
msgid "Search button"
msgstr "Chercher un bouton"
#: apps/note/views.py:99
msgid "Update button"
msgstr "Modifier le bouton"
#: apps/note/views.py:136 templates/base.html:94
msgid "Consumptions"
msgstr "Consommations"
#: apps/permission/models.py:81
#: apps/permission/models.py:83
#, python-brace-format
msgid "Can {type} {model}.{field} in {query}"
msgstr "Can {type} {model}.{field} in {query}"
#: apps/permission/models.py:83
#: apps/permission/models.py:85
#, python-brace-format
msgid "Can {type} {model} in {query}"
msgstr "Can {type} {model} in {query}"
#: apps/permission/models.py:96
#: apps/permission/models.py:98
msgid "rank"
msgstr "Rang"
#: apps/permission/models.py:109
#: apps/permission/models.py:111
msgid "permission mask"
msgstr "masque de permissions"
#: apps/permission/models.py:110
#: apps/permission/models.py:112
msgid "permission masks"
msgstr "masques de permissions"
#: apps/permission/models.py:150
#: apps/permission/models.py:152
msgid "query"
msgstr "requête"
#: apps/permission/models.py:163
#: apps/permission/models.py:165
msgid "mask"
msgstr "masque"
#: apps/permission/models.py:169
#: apps/permission/models.py:171
msgid "field"
msgstr "champ"
#: apps/permission/models.py:174
#: apps/permission/models.py:176
msgid ""
"Tells if the permission should be granted even if the membership of the user "
"is expired."
@ -889,33 +957,33 @@ msgstr ""
"Indique si la permission doit être attribuée même si l'adhésion de "
"l'utilisateur est expirée."
#: apps/permission/models.py:175 templates/permission/all_rights.html:26
#: apps/permission/models.py:177 templates/permission/all_rights.html:26
msgid "permanent"
msgstr "permanent"
#: apps/permission/models.py:186
#: apps/permission/models.py:188
msgid "permission"
msgstr "permission"
#: apps/permission/models.py:187 apps/permission/models.py:326
#: apps/permission/models.py:189 apps/permission/models.py:328
msgid "permissions"
msgstr "permissions"
#: apps/permission/models.py:192
#: apps/permission/models.py:194
msgid "Specifying field applies only to view and change permission types."
msgstr ""
"Spécifie le champ concerné, ne fonctionne que pour les permissions view et "
"change."
#: apps/permission/models.py:331
#: apps/permission/models.py:333
msgid "for club"
msgstr "s'applique au club"
#: apps/permission/models.py:341 apps/permission/models.py:342
#: apps/permission/models.py:343 apps/permission/models.py:344
msgid "role permissions"
msgstr "Permissions par rôles"
#: apps/permission/signals.py:62
#: apps/permission/signals.py:63
#, python-brace-format
msgid ""
"You don't have the permission to change the field {field} on this instance "
@ -924,7 +992,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}."
#: apps/permission/signals.py:72
#: apps/permission/signals.py:73
#, python-brace-format
msgid ""
"You don't have the permission to add this instance of model {app_label}."
@ -933,7 +1001,7 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter cette instance du modèle {app_label}."
"{model_name}."
#: apps/permission/signals.py:99
#: apps/permission/signals.py:101
#, python-brace-format
msgid ""
"You don't have the permission to delete this instance of model {app_label}."
@ -942,7 +1010,11 @@ msgstr ""
"Vous n'avez pas la permission de supprimer cette instance du modèle "
"{app_label}.{model_name}."
#: apps/permission/views.py:48
#: apps/permission/views.py:44 templates/base.html:135
msgid "Rights"
msgstr "Droits"
#: apps/permission/views.py:49
msgid "All rights"
msgstr "Tous les droits"
@ -971,37 +1043,61 @@ msgstr "Adhérer au club BDE"
msgid "Join Kfet Club"
msgstr "Adhérer au club Kfet"
#: apps/registration/views.py:79
#: apps/registration/views.py:38
msgid "Register new user"
msgstr "Enregistrer un nouvel utilisateur"
#: apps/registration/views.py:80
msgid "Email validation"
msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:125
#: apps/registration/views.py:82
msgid "Validate a registration"
msgstr "Valider l'inscription"
#: apps/registration/views.py:127
msgid "Email validation unsuccessful"
msgstr " La validation de l'adresse mail a échoué"
#: apps/registration/views.py:136
#: apps/registration/views.py:138
msgid "Email validation email sent"
msgstr "L'email de vérification de l'adresse email a bien été envoyé."
#: apps/registration/views.py:189
#: apps/registration/views.py:146
msgid "Resend email validation link"
msgstr "Renvoyer le lien de validation"
#: apps/registration/views.py:164
msgid "Pre-registered users list"
msgstr "Liste des utilisateurs en attente d'inscription"
#: apps/registration/views.py:193
msgid "Unregistered users"
msgstr "Utilisateurs en attente d'inscription"
#: apps/registration/views.py:256
#: apps/registration/views.py:206
msgid "Registration detail"
msgstr "Détails de l'inscription"
#: apps/registration/views.py:261
msgid "You must join the BDE."
msgstr "Vous devez adhérer au BDE."
#: apps/registration/views.py:278
#: apps/registration/views.py:283
msgid "You must join BDE club before joining Kfet club."
msgstr "Vous devez adhérer au club BDE avant d'adhérer au club Kfet."
#: apps/registration/views.py:283
#: apps/registration/views.py:288
msgid ""
"The entered amount is not enough for the memberships, should be at least {}"
msgstr ""
"Le montant crédité est trop faible pour adhérer, il doit être au minimum de "
"{}"
#: apps/registration/views.py:363
msgid "Invalidate pre-registration"
msgstr "Invalider l'inscription"
#: apps/treasury/apps.py:12 templates/base.html:126
msgid "Treasury"
msgstr "Trésorerie"
@ -1201,6 +1297,43 @@ msgstr "Oui"
msgid "No"
msgstr "Non"
#: apps/treasury/views.py:39
msgid "Create new invoice"
msgstr "Créer une nouvelle facture"
#: apps/treasury/views.py:82 templates/treasury/invoice_form.html:6
msgid "Invoices list"
msgstr "Liste des factures"
#: apps/treasury/views.py:91
msgid "Update an invoice"
msgstr "Modifier la facture"
#: apps/treasury/views.py:205
msgid "Create a new remittance"
msgstr "Créer une nouvelle remise"
#: apps/treasury/views.py:226 templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr "Liste des remises"
#: apps/treasury/views.py:276
msgid "Update a remittance"
msgstr "Modifier la remise"
#: apps/treasury/views.py:301
msgid "Attach a transaction to a remittance"
msgstr "Joindre une transaction à une remise"
#: apps/treasury/views.py:345
msgid "List of credits from the Société générale"
msgstr "Liste des crédits de la Société générale"
#: apps/treasury/views.py:384
msgid "Manage credits from the Société générale"
msgstr "Gérer les crédits de la Société générale"
#: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
#: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:131
msgid "WEI"
@ -1433,23 +1566,75 @@ msgstr "Nombre de membres"
msgid "members"
msgstr "adhérents"
#: apps/wei/views.py:203
#: apps/wei/views.py:55
msgid "Search WEI"
msgstr "Chercher un WEI"
#: apps/wei/views.py:64 templates/wei/weiclub_list.html:9
msgid "Create WEI"
msgstr "Créer un WEI"
#: apps/wei/views.py:84
msgid "WEI Detail"
msgstr "Détails du WEI"
#: apps/wei/views.py:179
msgid "View members of the WEI"
msgstr "Voir les membres du WEI"
#: apps/wei/views.py:207
msgid "Find WEI Membership"
msgstr "Trouver une adhésion au WEI"
#: apps/wei/views.py:238
#: apps/wei/views.py:217
msgid "View registrations to the WEI"
msgstr "Voir les inscriptions au WEI"
#: apps/wei/views.py:243
msgid "Find WEI Registration"
msgstr "Trouver une inscription au WEI"
#: apps/wei/views.py:447 templates/wei/weiclub_info.html:62
#: apps/wei/views.py:254
msgid "Update the WEI"
msgstr "Modifier le WEI"
#: apps/wei/views.py:275
msgid "Create new bus"
msgstr "Ajouter un nouveau bus"
#: apps/wei/views.py:306
msgid "Update bus"
msgstr "Modifier le bus"
#: apps/wei/views.py:336
msgid "Manage bus"
msgstr "Gérer le bus"
#: apps/wei/views.py:363
msgid "Create new team"
msgstr "Créer une nouvelle équipe"
#: apps/wei/views.py:395
msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/wei/views.py:426
msgid "Manage WEI team"
msgstr "Gérer l'équipe WEI"
#: apps/wei/views.py:448
msgid "Register first year student to the WEI"
msgstr "Inscrire un 1A au WEI"
#: apps/wei/views.py:460 templates/wei/weiclub_info.html:62
msgid "Register 1A"
msgstr "Inscrire un 1A"
#: apps/wei/views.py:468 apps/wei/views.py:537
#: apps/wei/views.py:481 apps/wei/views.py:551
msgid "This user is already registered to this WEI."
msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:473
#: apps/wei/views.py:486
msgid ""
"This user can't be in her/his first year since he/she has already participed "
"to a WEI."
@ -1457,23 +1642,39 @@ msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI."
#: apps/wei/views.py:501 templates/wei/weiclub_info.html:65
#: apps/wei/views.py:503
msgid "Register old student to the WEI"
msgstr "Inscrire un 2A+ au WEI"
#: apps/wei/views.py:515 templates/wei/weiclub_info.html:65
msgid "Register 2A+"
msgstr "Inscrire un 2A+"
#: apps/wei/views.py:519 apps/wei/views.py:606
#: apps/wei/views.py:533 apps/wei/views.py:621
msgid "You already opened an account in the Société générale."
msgstr "Vous avez déjà ouvert un compte auprès de la société générale."
#: apps/wei/views.py:666
#: apps/wei/views.py:581
msgid "Update WEI Registration"
msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:671
msgid "Delete WEI registration"
msgstr "Supprimer l'inscription WEI"
#: apps/wei/views.py:682
msgid "You don't have the right to delete this WEI registration."
msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI."
#: apps/wei/views.py:765
#: apps/wei/views.py:701
msgid "Validate WEI registration"
msgstr "Valider l'inscription WEI"
#: apps/wei/views.py:782
msgid "This user didn't give her/his caution check."
msgstr "Cet utilisateur n'a pas donné son chèque de caution."
#: apps/wei/views.py:839 apps/wei/views.py:859 apps/wei/views.py:869
#: apps/wei/views.py:819 apps/wei/views.py:872 apps/wei/views.py:882
#: templates/wei/survey.html:12 templates/wei/survey_closed.html:12
#: templates/wei/survey_end.html:12
msgid "Survey WEI"
@ -1617,15 +1818,9 @@ msgstr "Clubs"
msgid "Registrations"
msgstr "Inscriptions"
#: templates/base.html:135
msgid "Rights"
msgstr "Droits"
#: templates/base.html:139
#, fuzzy
#| msgid "registration"
msgid "Administration"
msgstr "inscription"
msgstr "Administration"
#: templates/base.html:178
msgid ""
@ -1685,15 +1880,11 @@ msgstr "Ajouter un membre"
msgid "View Profile"
msgstr "Voir le profil"
#: templates/member/club_list.html:8
msgid "search clubs"
msgstr "Chercher un club"
#: templates/member/club_list.html:12
#: templates/member/club_list.html:9
msgid "Create club"
msgstr "Créer un club"
#: templates/member/club_list.html:19
#: templates/member/club_list.html:16
msgid "Club listing"
msgstr "Liste des clubs"
@ -1737,10 +1928,6 @@ msgstr "mot de passe"
msgid "Change password"
msgstr "Changer le mot de passe"
#: templates/member/profile_info.html:43
msgid "Manage auth token"
msgstr "Gérer les jetons d'authentification"
#: templates/member/profile_tables.html:7
#: templates/registration/future_profile_detail.html:28
#: templates/wei/weimembership_form.html:30
@ -1838,31 +2025,23 @@ msgstr "Obsolète depuis"
msgid "Current price"
msgstr "Prix actuel"
#: templates/note/transactiontemplate_list.html:9
msgid "Search button"
msgstr "Chercher un bouton"
#: templates/note/transactiontemplate_list.html:11
#: templates/note/transactiontemplate_list.html:8
msgid "Name of the button..."
msgstr "Nom du bouton ..."
#: templates/note/transactiontemplate_list.html:16
msgid "Display visible buttons only"
msgstr "N'afficher que les boutons visibles uniquement"
#: templates/note/transactiontemplate_list.html:21
#: templates/note/transactiontemplate_list.html:10
msgid "New button"
msgstr "Nouveau bouton"
#: templates/note/transactiontemplate_list.html:28
#: templates/note/transactiontemplate_list.html:17
msgid "buttons listing "
msgstr "Liste des boutons"
#: templates/note/transactiontemplate_list.html:86
#: templates/note/transactiontemplate_list.html:55
msgid "button successfully deleted "
msgstr "Le bouton a bien été supprimé"
#: templates/note/transactiontemplate_list.html:90
#: templates/note/transactiontemplate_list.html:59
msgid "Unable to delete button "
msgstr "Impossible de supprimer le bouton "
@ -2077,10 +2256,6 @@ msgstr ""
"Vous devez également valider votre adresse email en suivant le lien que vous "
"avez reçu."
#: templates/treasury/invoice_form.html:6
msgid "Invoices list"
msgstr "Liste des factures"
#: templates/treasury/invoice_form.html:41
msgid "Add product"
msgstr "Ajouter produit"
@ -2103,11 +2278,6 @@ msgstr "Nouvelle facture"
msgid "Remittance #"
msgstr "Remise n°"
#: templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr "Liste des remises"
#: templates/treasury/remittance_form.html:12
msgid "Count"
msgstr "Nombre"
@ -2271,15 +2441,7 @@ msgstr "Ajouter un bus"
msgid "View WEI"
msgstr "Voir le WEI"
#: templates/wei/weiclub_list.html:8
msgid "search WEI"
msgstr "Chercher un WEI"
#: templates/wei/weiclub_list.html:12
msgid "Create WEI"
msgstr "Créer un WEI"
#: templates/wei/weiclub_list.html:19
#: templates/wei/weiclub_list.html:16
msgid "WEI listing"
msgstr "Liste des WEI"
@ -2293,7 +2455,7 @@ msgstr "M'inscrire au WEI ! 2A+"
#: templates/wei/weiclub_tables.html:67
msgid "Update my registration"
msgstr "Mettre à jour mon inscription"
msgstr "Modifier mon inscription"
#: templates/wei/weiclub_tables.html:92
msgid "Members of the WEI"
@ -2346,7 +2508,7 @@ msgstr "rôles préférés"
#: templates/wei/weimembership_form.html:128
#: templates/wei/weiregistration_confirm_delete.html:31
msgid "Update registration"
msgstr "Mettre à jour l'inscription"
msgstr "Modifier l'inscription"
#: templates/wei/weimembership_form.html:144
msgid "The registration is already validated and can't be unvalidated."

View File

@ -57,6 +57,8 @@ if "cas_server" in INSTALLED_APPS:
if "logs" in INSTALLED_APPS:
MIDDLEWARE += ('note_kfet.middlewares.SessionMiddleware',)
if DEBUG:
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
if "debug_toolbar" in INSTALLED_APPS:
MIDDLEWARE.insert(1, "debug_toolbar.middleware.DebugToolbarMiddleware")
INTERNAL_IPS = ['127.0.0.1']

View File

@ -13,7 +13,7 @@
"note": note_id
}
).done(function(){
$("#alias_table").load(location.href+ " #alias_table");
$("#alias_table").load(location.pathname+ " #alias_table");
addMsg("Alias ajouté","success");
})
.fail(function(xhr, textStatus, error){
@ -29,7 +29,7 @@
})
.done(function(){
addMsg('Alias supprimé','success');
$("#alias_table").load(location.href + " #alias_table");
$("#alias_table").load(location.pathname + " #alias_table");
})
.fail(function(xhr,textStatus, error){
errMsg(xhr.responseJSON);

View File

@ -95,6 +95,8 @@ function li(id, text, extra_css) {
* @param note The concerned note.
*/
function displayStyle(note) {
if (!note)
return "";
let balance = note.balance;
var css = "";
if (balance < -5000)
@ -130,7 +132,6 @@ function displayNote(note, alias, user_note_field = null, profile_pic_field = nu
if (profile_pic_field != null) {
$("#" + profile_pic_field).attr('src', img);
$("#" + profile_pic_field).click(function () {
console.log(note);
if (note.resourcetype === "NoteUser") {
document.location.href = "/accounts/user/" + note.user;
} else if (note.resourcetype === "NoteClub") {
@ -223,9 +224,7 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
// When the user type "Enter", the first alias is clicked
field.keypress(function (event) {
console.log(notes);
if (event.originalEvent.charCode === 13 && notes.length > 0) {
console.log(42);
let li_obj = field.parent().find("ul li").first();
displayNote(notes[0], li_obj.text(), user_note_field, profile_pic_field);
li_obj.trigger("click");
@ -277,7 +276,6 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
field.attr('data-original-title', aliases_matched_html).tooltip('show');
consumers.results.forEach(function (consumer) {
let note = consumer.note;
let consumer_obj = $("#" + alias_prefix + "_" + consumer.id);
consumer_obj.hover(function () {
displayNote(consumer.note, consumer.name, user_note_field, profile_pic_field)
@ -285,8 +283,8 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
consumer_obj.click(function () {
var disp = null;
notes_display.forEach(function (d) {
// We compare the note ids
if (d.id === note.id) {
// We compare the alias ids
if (d.id === consumer.id) {
d.quantity += 1;
disp = d;
}
@ -296,7 +294,7 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
disp = {
name: consumer.name,
id: consumer.id,
note: note,
note: consumer.note,
quantity: 1
};
notes_display.push(disp);
@ -345,7 +343,7 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
// When a validate button is clicked, we switch the validation status
function de_validate(id, validated) {
let invalidity_reason = $("#invalidity_reason_" + id).val();
$("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>");
$("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳</strong>");
// Perform a PATCH request to the API in order to update the transaction
// If the user has insufficient rights, an error message will appear

View File

@ -7,7 +7,7 @@ function refreshHistory() {
$("#history").load("/note/transfer/ #history");
}
function reset() {
function reset(refresh=true) {
sources_notes_display.length = 0;
sources.length = 0;
dests_notes_display.length = 0;
@ -21,9 +21,11 @@ function reset() {
$("#bank").val("");
$("#user_note").val("");
$("#profile_pic").attr("src", "/media/pic/default.png");
if (refresh) {
refreshBalance();
refreshHistory();
}
}
$(document).ready(function() {
/**
@ -138,15 +140,18 @@ $(document).ready(function() {
$("#source_me").click(function() {
// Shortcut to set the current user as the only emitter
reset();
reset(false);
let source_note = $("#source_note");
source_note.focus();
source_note.val(username);
source_note.val("");
let event = jQuery.Event("keyup");
event.originalEvent = {charCode: 0};
event.originalEvent = {charCode: 97};
source_note.trigger(event);
source_note.val(username);
event = jQuery.Event("keyup");
event.originalEvent = {charCode: 97};
source_note.trigger(event);
console.log(sources.length);
let fill_note = function() {
if (sources.length === 0) {
setTimeout(fill_note, 100);

View File

@ -92,7 +92,7 @@
})
.done(function() {
addMsg('Invité supprimé','success');
$("#guests_table").load(location.href + " #guests_table");
$("#guests_table").load(location.pathname + " #guests_table");
})
.fail(function(xhr, textStatus, error) {
errMsg(xhr.responseJSON);

View File

@ -51,7 +51,7 @@
if ((pattern === old_pattern || pattern === "") && !force)
return;
$("#entry_table").load(location.href + "?search=" + pattern.replace(" ", "%20") + " #entry_table", init);
$("#entry_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + " #entry_table", init);
refreshBalance();
}

View File

@ -4,9 +4,6 @@
{% block content %}
<div class="row justify-content-center mb-4">
<div class="col-md-10 text-center">
<h4>
{% trans "search clubs" %}
</h4>
<input class="form-control mx-auto w-25" type="text" id="search_field"/>
<hr>
<a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}">{% trans "Create club" %}</a>
@ -36,7 +33,7 @@
function reloadTable() {
let pattern = searchbar_obj.val();
$("#club_table").load(location.href + "?search=" + pattern.replace(" ", "%20") + " #club_table", init);
$("#club_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + " #club_table", init);
}
searchbar_obj.keyup(function() {

View File

@ -34,7 +34,7 @@
if (pattern === old_pattern || pattern === "")
return;
$("#user_table").load(location.href + "?search=" + pattern.replace(" ", "%20") + " #user_table", init);
$("#user_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + " #user_table", init);
}
searchbar_obj.keyup(function() {

View File

@ -56,9 +56,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
<div class="card-body">
<input class="form-control mx-auto d-block" type="text" id="source_note" placeholder="{% trans "Name or alias..." %}" />
<hr>
<button class="form-control mx-auto d-block btn btn-secondary" id="source_me">
<span class="form-control mx-auto d-block btn btn-secondary" id="source_me">
{% trans "I am the emitter" %}
</button>
</span>
</div>
</div>
</div>

View File

@ -5,18 +5,7 @@
{% block content %}
<div class="row justify-content-center mb-4">
<div class="col-md-10 text-center">
<h4>
{% trans "Search button" %}
</h4>
<input class="form-control mx-auto w-25" type="text" id="search_field" placeholder="{% trans "Name of the button..." %}">
<div class="form-group">
<div id="div_active_only" class="form-check">
<label for="active_only" class="form-check-label">
<input type="checkbox" name="active_only" class="checkboxinput form-check-input" checked="" id="active_only">
{% trans "Display visible buttons only" %}
</label>
</div>
</div>
<hr>
<a class="btn btn-primary text-center my-1" href="{% url 'note:template_create' %}">{% trans "New button" %}</a>
</div>
@ -36,45 +25,25 @@
{% endblock %}
{% block extrajavascript %}
<script>
/* fonction appelée à la fin du timer */
function getInfo() {
var asked = $("#search_field").val();
/* on ne fait la requête que si on a au moins un caractère pour chercher */
if (asked.length >= 1) {
$.getJSON("/api/note/transaction/template/?format=json&search=" + asked + ($("#active_only").is(":checked") ? "&display=true" : ""), function(buttons) {
console.log(buttons);
let selected_id = buttons.results.map((a => "#row-" + a.id));
console.log(".table-row " + selected_id.join());
$(".table-row " + selected_id.join()).removeClass('d-none');
$(".table-row").not(selected_id.join()).addClass('d-none');
});
}
else {
if ($("#active_only").is(":checked")) {
$('.table-success').removeClass('d-none');
$('.table-danger').addClass('d-none');
}
else {
// show everything
$('table tr').removeClass('d-none');
}
}
<script type="text/javascript">
$(document).ready(function() {
let searchbar_obj = $("#search_field");
var timer_on = false;
var timer;
function reloadTable() {
let pattern = searchbar_obj.val();
$("#buttons_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + " #buttons_table");
}
var timer;
var timer_on;
/* Fontion appelée quand le texte change (délenche le timer) */
function search_field_moved() {
if (timer_on) { // Si le timer a déjà été lancé, on réinitialise le compteur.
searchbar_obj.keyup(function() {
if (timer_on)
clearTimeout(timer);
timer = setTimeout(getInfo, 300);
}
else { // Sinon, on le lance et on enregistre le fait qu'il tourne.
timer = setTimeout(getInfo, 300);
timer_on = true;
}
}
setTimeout(reloadTable, 0);
});
});
// on click of button "delete" , call the API
function delete_button(button_id) {
$.ajax({
@ -84,18 +53,11 @@
})
.done(function() {
addMsg('{% trans "button successfully deleted "%}','success');
$("#buttons_table").load("{% url 'note:template_list' %} #buttons_table");
$("#buttons_table").load(location.pathname + "?search=" + $("#search_field").val().replace(" ", "%20") + " #buttons_table");
})
.fail(function() {
addMsg('{% trans "Unable to delete button "%} #' + button_id, 'danger')
});
}
$(document).ready(function() {
$("#search_field").keyup(search_field_moved);
$("#active_only").change(search_field_moved);
search_field_moved();
});
</script>
{% endblock %}

View File

@ -32,7 +32,7 @@
if (pattern === old_pattern || pattern === "")
return;
$("#user_table").load(location.href + "?search=" + pattern.replace(" ", "%20") + " #user_table", init);
$("#user_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + " #user_table", init);
$(".table-row").click(function() {
window.document.location = $(this).data("href");

View File

@ -4,9 +4,6 @@
{% block content %}
<div class="row justify-content-center mb-4">
<div class="col-md-10 text-center">
<h4>
{% trans "search WEI" %}
</h4>
<input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved()" id="search_field"/>
<hr>
<a class="btn btn-primary text-center my-4" href="{% url 'wei:wei_create' %}">{% trans "Create WEI" %}</a>