💥 Improve performances

This commit is contained in:
Yohann D'ANELLO 2020-07-25 17:25:57 +02:00
parent 50024dc03d
commit 2eb601bd66
29 changed files with 2387 additions and 774 deletions

View File

@ -129,7 +129,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
user = context['user_object']
history_list = \
Transaction.objects.all().filter(Q(source=user.note) | Q(destination=user.note))\
.order_by("-created_at", "-id")\
.order_by("-created_at")\
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))
history_table = HistoryTable(history_list, prefix='transaction-')
history_table.paginate(per_page=20, page=self.request.GET.get("transaction-page", 1))
@ -155,7 +155,7 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
Filter the user list with the given pattern.
"""
qs = super().get_queryset().filter(profile__registration_valid=True)
qs = super().get_queryset().distinct().filter(profile__registration_valid=True)
if "search" in self.request.GET:
pattern = self.request.GET["search"]
@ -332,7 +332,7 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\
.order_by('-created_at', '-id')
.order_by('-created_at')
history_table = HistoryTable(club_transactions, prefix="history-")
history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1))
context['history_list'] = history_table

View File

@ -62,6 +62,7 @@ class TransactionTemplate(models.Model):
category = models.ForeignKey(
TemplateCategory,
on_delete=models.PROTECT,
related_name='templates',
verbose_name=_('type'),
max_length=31,
)
@ -71,6 +72,11 @@ class TransactionTemplate(models.Model):
verbose_name=_("display"),
)
highlighted = models.BooleanField(
default=False,
verbose_name=_("highlighted"),
)
description = models.CharField(
verbose_name=_('description'),
max_length=255,

View File

@ -14,7 +14,7 @@ from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin
from .forms import TransactionTemplateForm
from .models import Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial
from .models import TemplateCategory, Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial
from .models.transactions import SpecialTransaction
from .tables import HistoryTable, ButtonTable
@ -31,7 +31,7 @@ class TransactionCreateView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTabl
table_class = HistoryTable
def get_queryset(self, **kwargs):
return super().get_queryset(**kwargs).order_by("-created_at", "-id").all()[:20]
return super().get_queryset(**kwargs).order_by("-created_at").all()[:20]
def get_context_data(self, **kwargs):
"""
@ -121,19 +121,22 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
table_class = HistoryTable
def get_queryset(self, **kwargs):
return super().get_queryset(**kwargs).order_by("-created_at", "-id")[:20]
return super().get_queryset(**kwargs).order_by("-created_at")[:20]
def get_context_data(self, **kwargs):
"""
Add some context variables in template such as page title
"""
context = super().get_context_data(**kwargs)
from django.db.models import Count
buttons = TransactionTemplate.objects.filter(
categories = TemplateCategory.objects.order_by('name').all()
for category in categories:
category.templates_filtered = category.templates.filter(
PermissionBackend().filter_queryset(self.request.user, TransactionTemplate, "view")
).filter(display=True).annotate(clicks=Count('recurrenttransaction')).order_by('category__name', 'name')
context['transaction_templates'] = buttons
context['most_used'] = buttons.order_by('-clicks', 'name')[:10]
).filter(display=True).order_by('name').all()
context['categories'] = [cat for cat in categories if cat.templates_filtered]
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

View File

@ -40,7 +40,7 @@ def not_empty_model_change_list(model_name):
@stringfilter
def model_list(model_name, t="view"):
def model_list(model_name, t="view", fetch=True):
"""
Return the queryset of all visible instances of the given model.
"""
@ -49,10 +49,20 @@ def model_list(model_name, t="view"):
return False
spl = model_name.split(".")
ct = ContentType.objects.get(app_label=spl[0], model=spl[1])
qs = ct.model_class().objects.filter(PermissionBackend.filter_queryset(user, ct, t)).all()
qs = ct.model_class().objects.filter(PermissionBackend.filter_queryset(user, ct, t))
if fetch:
qs = qs.all()
return qs
@stringfilter
def model_list_length(model_name, t="view"):
"""
Return the length of queryset of all visible instances of the given model.
"""
return model_list(model_name, t, False).count()
def has_perm(perm, obj):
return PermissionBackend.check_perm(get_current_authenticated_user(), perm, obj)
@ -85,4 +95,5 @@ register = template.Library()
register.filter('not_empty_model_list', not_empty_model_list)
register.filter('not_empty_model_change_list', not_empty_model_change_list)
register.filter('model_list', model_list)
register.filter('model_list_length', model_list_length)
register.filter('has_perm', has_perm)

View File

@ -19,7 +19,7 @@ class ProtectQuerysetMixin:
"""
def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs)
return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view")).distinct()
return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view"))
def get_form(self, form_class=None):
form = super().get_form(form_class)

@ -1 +1 @@
Subproject commit f5967359a95b6be8739ba8a43419de06c9bc9587
Subproject commit 580948fe1da1904ba6418daafb48a0a64824a11b

View File

@ -132,8 +132,7 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
# Add submit button
self.helper.add_input(Submit('submit', _("Submit"), attr={'class': 'btn btn-block btn-primary'}))
self.fields["remittance"].queryset = Remittance.objects.filter(closed=False)\
.filter(PermissionBackend.filter_queryset(self.request.user, Remittance, "view"))
self.fields["remittance"].queryset = Remittance.objects.filter(closed=False)
def clean_last_name(self):
"""

View File

@ -222,23 +222,41 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["opened_remittances"] = RemittanceTable(
opened_remittances = RemittanceTable(
data=Remittance.objects.filter(closed=False).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all())
context["closed_remittances"] = RemittanceTable(
data=Remittance.objects.filter(closed=True).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).reverse().all())
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
prefix="opened-remittances-",
)
opened_remittances.paginate(page=self.request.GET.get("opened-remittances-page", 1), per_page=10)
context["opened_remittances"] = opened_remittances
context["special_transactions_no_remittance"] = SpecialTransactionTable(
closed_remittances = RemittanceTable(
data=Remittance.objects.filter(closed=True).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).reverse().all(),
prefix="closed-remittances-",
)
closed_remittances.paginate(page=self.request.GET.get("closed-remittances-page", 1), per_page=10)
context["closed_remittances"] = closed_remittances
no_remittance_tr = SpecialTransactionTable(
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
specialtransactionproxy__remittance=None).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
exclude=('remittance_remove', ))
context["special_transactions_with_remittance"] = SpecialTransactionTable(
exclude=('remittance_remove', ),
prefix="no-remittance-",
)
no_remittance_tr.paginate(page=self.request.GET.get("no-remittance-page", 1), per_page=10)
context["special_transactions_no_remittance"] = no_remittance_tr
with_remittance_tr = SpecialTransactionTable(
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
specialtransactionproxy__remittance__closed=False).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
exclude=('remittance_add', ))
exclude=('remittance_add', ),
prefix="with-remittance-",
)
with_remittance_tr.paginate(page=self.request.GET.get("with-remittance-page", 1), per_page=10)
context["special_transactions_with_remittance"] = with_remittance_tr
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-05-07 20:56+0200\n"
"POT-Creation-Date: 2020-07-25 16:50+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/member/models.py:255
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:249
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:261
#: apps/wei/models.py:64 templates/member/club_info.html:13
#: templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16
@ -70,7 +70,7 @@ msgstr ""
msgid "activity types"
msgstr ""
#: apps/activity/models.py:53 apps/note/models/transactions.py:75
#: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:103 apps/permission/models.py:182
#: apps/wei/models.py:70 apps/wei/models.py:126
#: templates/activity/activity_detail.html:16
@ -78,7 +78,7 @@ msgid "description"
msgstr ""
#: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:65 apps/permission/models.py:157
#: apps/note/models/transactions.py:66 apps/permission/models.py:157
#: templates/activity/activity_detail.html:19
msgid "type"
msgstr ""
@ -106,7 +106,7 @@ msgstr ""
msgid "end date"
msgstr ""
#: apps/activity/models.py:93 apps/note/models/transactions.py:140
#: apps/activity/models.py:93 apps/note/models/transactions.py:146
#: templates/activity/activity_detail.html:47
msgid "valid"
msgstr ""
@ -201,11 +201,11 @@ msgstr ""
msgid "Note"
msgstr ""
#: apps/activity/tables.py:83 apps/member/tables.py:41
#: apps/activity/tables.py:83 apps/member/tables.py:42
msgid "Balance"
msgstr ""
#: apps/activity/views.py:46 templates/base.html:120
#: apps/activity/views.py:44 templates/base.html:120
msgid "Activities"
msgstr ""
@ -509,11 +509,11 @@ msgstr ""
msgid "fee"
msgstr ""
#: apps/member/models.py:320 apps/member/views.py:505 apps/wei/views.py:768
#: apps/member/models.py:320 apps/member/views.py:521 apps/wei/views.py:768
msgid "User is not a member of the parent club"
msgstr ""
#: apps/member/models.py:330 apps/member/views.py:514
#: apps/member/models.py:330 apps/member/views.py:530
msgid "User is already a member of the club"
msgstr ""
@ -530,7 +530,7 @@ msgstr ""
msgid "memberships"
msgstr ""
#: apps/member/tables.py:112
#: apps/member/tables.py:113
msgid "Renew"
msgstr ""
@ -552,32 +552,32 @@ msgstr ""
msgid "Search user"
msgstr ""
#: apps/member/views.py:500 apps/wei/views.py:759
#: apps/member/views.py:516 apps/wei/views.py:759
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
msgstr ""
#: apps/member/views.py:518
#: apps/member/views.py:534
msgid "The membership must start after {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:523
#: apps/member/views.py:539
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:540 apps/member/views.py:542 apps/member/views.py:544
#: apps/member/views.py:556 apps/member/views.py:558 apps/member/views.py:560
#: apps/registration/views.py:289 apps/registration/views.py:291
#: apps/registration/views.py:293
msgid "This field is required."
msgstr ""
#: apps/note/admin.py:120 apps/note/models/transactions.py:100
#: apps/note/admin.py:120 apps/note/models/transactions.py:106
msgid "source"
msgstr ""
#: apps/note/admin.py:128 apps/note/admin.py:170
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:113
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr ""
@ -619,7 +619,7 @@ msgstr ""
msgid "display image"
msgstr ""
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:123
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:129
msgid "created at"
msgstr ""
@ -702,7 +702,7 @@ msgstr ""
msgid "A template with this name already exist"
msgstr ""
#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:131
#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:137
msgid "amount"
msgstr ""
@ -710,78 +710,94 @@ msgstr ""
msgid "in centimes"
msgstr ""
#: apps/note/models/transactions.py:71
#: apps/note/models/transactions.py:72
msgid "display"
msgstr ""
#: apps/note/models/transactions.py:81
#: apps/note/models/transactions.py:77
msgid "highlighted"
msgstr ""
#: apps/note/models/transactions.py:87
msgid "transaction template"
msgstr ""
#: apps/note/models/transactions.py:82
#: apps/note/models/transactions.py:88
msgid "transaction templates"
msgstr ""
#: apps/note/models/transactions.py:106 apps/note/models/transactions.py:119
#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
#: apps/note/tables.py:33 apps/note/tables.py:42
msgid "used alias"
msgstr ""
#: apps/note/models/transactions.py:127
#: apps/note/models/transactions.py:133
msgid "quantity"
msgstr ""
#: apps/note/models/transactions.py:135
#: apps/note/models/transactions.py:141
msgid "reason"
msgstr ""
#: apps/note/models/transactions.py:145 apps/note/tables.py:95
#: apps/note/models/transactions.py:151 apps/note/tables.py:95
msgid "invalidity reason"
msgstr ""
#: apps/note/models/transactions.py:153
#: apps/note/models/transactions.py:159
msgid "transaction"
msgstr ""
#: apps/note/models/transactions.py:154
#: apps/note/models/transactions.py:160
#: templates/treasury/sogecredit_detail.html:22
msgid "transactions"
msgstr ""
#: apps/note/models/transactions.py:216
#: apps/note/models/transactions.py:175
msgid ""
"The transaction can't be saved since the source note or the destination note "
"is not active."
msgstr ""
#: apps/note/models/transactions.py:228
#: templates/activity/activity_entry.html:13 templates/base.html:98
#: templates/note/transaction_form.html:19
#: templates/note/transaction_form.html:140
msgid "Transfer"
msgstr ""
#: apps/note/models/transactions.py:239
#: apps/note/models/transactions.py:251
msgid "Template"
msgstr ""
#: apps/note/models/transactions.py:254
#: apps/note/models/transactions.py:266
msgid "first_name"
msgstr ""
#: apps/note/models/transactions.py:259
#: apps/note/models/transactions.py:271
msgid "bank"
msgstr ""
#: apps/note/models/transactions.py:265
#: apps/note/models/transactions.py:277
#: templates/activity/activity_entry.html:17
#: templates/note/transaction_form.html:24
msgid "Credit"
msgstr ""
#: apps/note/models/transactions.py:265 templates/note/transaction_form.html:28
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:28
msgid "Debit"
msgstr ""
#: apps/note/models/transactions.py:281 apps/note/models/transactions.py:286
#: apps/note/models/transactions.py:288
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
msgstr ""
#: apps/note/models/transactions.py:305 apps/note/models/transactions.py:310
msgid "membership transaction"
msgstr ""
#: apps/note/models/transactions.py:282 apps/treasury/models.py:227
#: apps/note/models/transactions.py:306 apps/treasury/models.py:227
msgid "membership transactions"
msgstr ""
@ -814,7 +830,7 @@ msgstr ""
msgid "Transfer money"
msgstr ""
#: apps/note/views.py:137 templates/base.html:93
#: apps/note/views.py:140 templates/base.html:93
msgid "Consumptions"
msgstr ""
@ -1692,7 +1708,7 @@ msgid "Consume!"
msgstr ""
#: templates/note/conso_form.html:71
msgid "Most used buttons"
msgid "Highlighted buttons"
msgstr ""
#: templates/note/conso_form.html:134
@ -2030,6 +2046,10 @@ msgstr ""
msgid "Closed remittances"
msgstr ""
#: templates/treasury/remittance_list.html:62
msgid "There is no closed remittance yet."
msgstr ""
#: templates/treasury/sogecredit_detail.html:29
msgid "total amount"
msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-07 20:56+0200\n"
"POT-Creation-Date: 2020-07-25 16:50+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/member/models.py:255
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:249
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:261
#: apps/wei/models.py:64 templates/member/club_info.html:13
#: templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16
@ -71,7 +71,7 @@ msgstr "type d'activité"
msgid "activity types"
msgstr "types d'activité"
#: apps/activity/models.py:53 apps/note/models/transactions.py:75
#: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:103 apps/permission/models.py:182
#: apps/wei/models.py:70 apps/wei/models.py:126
#: templates/activity/activity_detail.html:16
@ -79,7 +79,7 @@ msgid "description"
msgstr "description"
#: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:65 apps/permission/models.py:157
#: apps/note/models/transactions.py:66 apps/permission/models.py:157
#: templates/activity/activity_detail.html:19
msgid "type"
msgstr "type"
@ -107,7 +107,7 @@ msgstr "date de début"
msgid "end date"
msgstr "date de fin"
#: apps/activity/models.py:93 apps/note/models/transactions.py:140
#: apps/activity/models.py:93 apps/note/models/transactions.py:146
#: templates/activity/activity_detail.html:47
msgid "valid"
msgstr "valide"
@ -202,11 +202,11 @@ msgstr "Prénom"
msgid "Note"
msgstr "Note"
#: apps/activity/tables.py:83 apps/member/tables.py:41
#: apps/activity/tables.py:83 apps/member/tables.py:42
msgid "Balance"
msgstr "Solde du compte"
#: apps/activity/views.py:46 templates/base.html:120
#: apps/activity/views.py:44 templates/base.html:120
msgid "Activities"
msgstr "Activités"
@ -514,11 +514,11 @@ msgstr "l'adhésion finit le"
msgid "fee"
msgstr "cotisation"
#: apps/member/models.py:320 apps/member/views.py:505 apps/wei/views.py:768
#: apps/member/models.py:320 apps/member/views.py:521 apps/wei/views.py:768
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
#: apps/member/models.py:330 apps/member/views.py:514
#: apps/member/models.py:330 apps/member/views.py:530
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
@ -535,7 +535,7 @@ msgstr "adhésion"
msgid "memberships"
msgstr "adhésions"
#: apps/member/tables.py:112
#: apps/member/tables.py:113
msgid "Renew"
msgstr "Renouveler"
@ -557,7 +557,7 @@ msgstr "Un alias avec un nom similaire existe déjà."
msgid "Search user"
msgstr "Chercher un utilisateur"
#: apps/member/views.py:500 apps/wei/views.py:759
#: apps/member/views.py:516 apps/wei/views.py:759
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@ -565,26 +565,26 @@ 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:518
#: apps/member/views.py:534
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:523
#: apps/member/views.py:539
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:540 apps/member/views.py:542 apps/member/views.py:544
#: apps/member/views.py:556 apps/member/views.py:558 apps/member/views.py:560
#: apps/registration/views.py:289 apps/registration/views.py:291
#: apps/registration/views.py:293
msgid "This field is required."
msgstr "Ce champ est requis."
#: apps/note/admin.py:120 apps/note/models/transactions.py:100
#: apps/note/admin.py:120 apps/note/models/transactions.py:106
msgid "source"
msgstr "source"
#: apps/note/admin.py:128 apps/note/admin.py:170
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:113
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr "destination"
@ -627,7 +627,7 @@ msgstr ""
msgid "display image"
msgstr "image affichée"
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:123
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:129
msgid "created at"
msgstr "créée le"
@ -710,7 +710,7 @@ msgstr "catégories de transaction"
msgid "A template with this name already exist"
msgstr "Un modèle de transaction avec un nom similaire existe déjà."
#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:131
#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:137
msgid "amount"
msgstr "montant"
@ -718,78 +718,94 @@ msgstr "montant"
msgid "in centimes"
msgstr "en centimes"
#: apps/note/models/transactions.py:71
#: apps/note/models/transactions.py:72
msgid "display"
msgstr "afficher"
#: apps/note/models/transactions.py:81
#: apps/note/models/transactions.py:77
msgid "highlighted"
msgstr ""
#: apps/note/models/transactions.py:87
msgid "transaction template"
msgstr "modèle de transaction"
#: apps/note/models/transactions.py:82
#: apps/note/models/transactions.py:88
msgid "transaction templates"
msgstr "modèles de transaction"
#: apps/note/models/transactions.py:106 apps/note/models/transactions.py:119
#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
#: apps/note/tables.py:33 apps/note/tables.py:42
msgid "used alias"
msgstr "alias utilisé"
#: apps/note/models/transactions.py:127
#: apps/note/models/transactions.py:133
msgid "quantity"
msgstr "quantité"
#: apps/note/models/transactions.py:135
#: apps/note/models/transactions.py:141
msgid "reason"
msgstr "raison"
#: apps/note/models/transactions.py:145 apps/note/tables.py:95
#: apps/note/models/transactions.py:151 apps/note/tables.py:95
msgid "invalidity reason"
msgstr "Motif d'invalidité"
#: apps/note/models/transactions.py:153
#: apps/note/models/transactions.py:159
msgid "transaction"
msgstr "transaction"
#: apps/note/models/transactions.py:154
#: apps/note/models/transactions.py:160
#: templates/treasury/sogecredit_detail.html:22
msgid "transactions"
msgstr "transactions"
#: apps/note/models/transactions.py:216
#: apps/note/models/transactions.py:175
msgid ""
"The transaction can't be saved since the source note or the destination note "
"is not active."
msgstr ""
#: apps/note/models/transactions.py:228
#: templates/activity/activity_entry.html:13 templates/base.html:98
#: templates/note/transaction_form.html:19
#: templates/note/transaction_form.html:140
msgid "Transfer"
msgstr "Virement"
#: apps/note/models/transactions.py:239
#: apps/note/models/transactions.py:251
msgid "Template"
msgstr "Bouton"
#: apps/note/models/transactions.py:254
#: apps/note/models/transactions.py:266
msgid "first_name"
msgstr "prénom"
#: apps/note/models/transactions.py:259
#: apps/note/models/transactions.py:271
msgid "bank"
msgstr "banque"
#: apps/note/models/transactions.py:265
#: apps/note/models/transactions.py:277
#: templates/activity/activity_entry.html:17
#: templates/note/transaction_form.html:24
msgid "Credit"
msgstr "Crédit"
#: apps/note/models/transactions.py:265 templates/note/transaction_form.html:28
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:28
msgid "Debit"
msgstr "Débit"
#: apps/note/models/transactions.py:281 apps/note/models/transactions.py:286
#: apps/note/models/transactions.py:288
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
msgstr ""
#: apps/note/models/transactions.py:305 apps/note/models/transactions.py:310
msgid "membership transaction"
msgstr "Transaction d'adhésion"
#: apps/note/models/transactions.py:282 apps/treasury/models.py:227
#: apps/note/models/transactions.py:306 apps/treasury/models.py:227
msgid "membership transactions"
msgstr "Transactions d'adhésion"
@ -822,7 +838,7 @@ msgstr "Éditer"
msgid "Transfer money"
msgstr "Transférer de l'argent"
#: apps/note/views.py:137 templates/base.html:93
#: apps/note/views.py:140 templates/base.html:93
msgid "Consumptions"
msgstr "Consommations"
@ -865,8 +881,8 @@ msgid ""
"Tells if the permission should be granted even if the membership of the user "
"is expired."
msgstr ""
"Indique si la permission doit être attribuée même si l'adhésion de l'utilisateur "
"est expirée."
"Indique si la permission doit être attribuée même si l'adhésion de "
"l'utilisateur est expirée."
#: apps/permission/models.py:176 templates/permission/all_rights.html:26
msgid "permanent"
@ -1750,8 +1766,8 @@ msgid "Consume!"
msgstr "Consommer !"
#: templates/note/conso_form.html:71
msgid "Most used buttons"
msgstr "Boutons les plus utilisés"
msgid "Highlighted buttons"
msgstr "Boutons mis en avant"
#: templates/note/conso_form.html:134
msgid "Single consumptions"
@ -2117,6 +2133,10 @@ msgstr "Il n'y a pas de transaction associée à une remise ouverte."
msgid "Closed remittances"
msgstr "Remises fermées"
#: templates/treasury/remittance_list.html:62
msgid "There is no closed remittance yet."
msgstr "Il n'y a pas encore de remise fermée."
#: templates/treasury/sogecredit_detail.html:29
msgid "total amount"
msgstr "montant total"

View File

@ -61,6 +61,7 @@ INSTALLED_APPS = [
'note',
'permission',
'registration',
'scripts',
'treasury',
'wei',
]

View File

@ -1,10 +1,4 @@
Copyright jQuery Foundation and other contributors, https://jquery.org/
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/jquery/jquery
====
Copyright JS Foundation and other contributors, https://js.foundation/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
#djDebug {
display: none !important;
}

View File

@ -0,0 +1,646 @@
/* http://www.positioniseverything.net/easyclearing.html */
#djDebug .djdt-clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
#djDebug .djdt-clearfix {display: inline-block;}
/* Hides from IE-mac \*/
#djDebug .djdt-clearfix {display: block;}
* html #djDebug .djdt-clearfix {height: 1%;}
/* end hide from IE-mac */
/* Debug Toolbar CSS Reset, adapted from Eric Meyer's CSS Reset */
#djDebug {color:#000;background:#FFF;}
#djDebug, #djDebug div, #djDebug span, #djDebug applet, #djDebug object, #djDebug iframe,
#djDebug h1, #djDebug h2, #djDebug h3, #djDebug h4, #djDebug h5, #djDebug h6, #djDebug p, #djDebug blockquote, #djDebug pre,
#djDebug a, #djDebug abbr, #djDebug acronym, #djDebug address, #djDebug big, #djDebug cite, #djDebug code,
#djDebug del, #djDebug dfn, #djDebug em, #djDebug font, #djDebug img, #djDebug ins, #djDebug kbd, #djDebug q, #djDebug s, #djDebug samp,
#djDebug small, #djDebug strike, #djDebug strong, #djDebug sub, #djDebug sup, #djDebug tt, #djDebug var,
#djDebug b, #djDebug u, #djDebug i, #djDebug center,
#djDebug dl, #djDebug dt, #djDebug dd, #djDebug ol, #djDebug ul, #djDebug li,
#djDebug fieldset, #djDebug form, #djDebug label, #djDebug legend,
#djDebug table, #djDebug caption, #djDebug tbody, #djDebug tfoot, #djDebug thead, #djDebug tr, #djDebug th, #djDebug td,
#djDebug button {
margin:0;
padding:0;
min-width:0;
width:auto;
border:0;
outline:0;
font-size:12px;
line-height:1.5em;
color:#000;
vertical-align:baseline;
background-color:transparent;
font-family:sans-serif;
text-align:left;
text-shadow: none;
white-space: normal;
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
#djDebug button, #djDebug a.button {
background-color: #eee;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #cccccc));
background-image: -webkit-linear-gradient(top, #eee, #cccccc);
background-image: -moz-linear-gradient(top, #eee, #cccccc);
background-image: -ms-linear-gradient(top, #eee, #cccccc);
background-image: -o-linear-gradient(top, #eee, #cccccc);
background-image: linear-gradient(top, #eee, #cccccc);
border: 1px solid #ccc;
border-bottom: 1px solid #bbb;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
color: #333;
line-height: 1;
padding: 0 8px;
text-align: center;
text-shadow: 0 1px 0 #eee;
}
#djDebug button:hover, #djDebug a.button:hover {
background-color: #ddd;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ddd), color-stop(100%, #bbb));
background-image: -webkit-linear-gradient(top, #ddd, #bbb);
background-image: -moz-linear-gradient(top, #ddd, #bbb);
background-image: -ms-linear-gradient(top, #ddd, #bbb);
background-image: -o-linear-gradient(top, #ddd, #bbb);
background-image: linear-gradient(top, #ddd, #bbb);
border-color: #bbb;
border-bottom-color: #999;
cursor: pointer;
text-shadow: 0 1px 0 #ddd;
}
#djDebug button:active, #djDebug a.button:active {
border: 1px solid #aaa;
border-bottom: 1px solid #888;
-webkit-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
-moz-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
}
#djDebug #djDebugToolbar {
background-color:#111;
width:200px;
z-index:100000000;
position:fixed;
top:0;
bottom:0;
right:0;
opacity:0.9;
overflow-y: auto;
}
#djDebug #djDebugToolbar small {
color:#999;
}
#djDebug #djDebugToolbar ul {
margin:0;
padding:0;
list-style:none;
}
#djDebug #djDebugToolbar li {
border-bottom:1px solid #222;
color:#fff;
display:block;
font-weight:bold;
float:none;
margin:0;
padding:0;
position:relative;
width:auto;
}
#djDebug #djDebugToolbar input[type=checkbox] {
float: right;
margin: 10px;
}
#djDebug #djDebugToolbar li>a,
#djDebug #djDebugToolbar li>div.djdt-contentless {
font-weight:normal;
font-style:normal;
text-decoration:none;
display:block;
font-size:16px;
padding:10px 10px 5px 25px;
color:#fff;
}
#djDebug #djDebugToolbar li>div.djdt-disabled {
font-style: italic;
color: #999;
}
#djDebug #djDebugToolbar li a:hover {
color:#111;
background-color:#ffc;
}
#djDebug #djDebugToolbar li.djdt-active {
background: #333 no-repeat left center;
background-image: url(../img/indicator.png);
padding-left:10px;
}
#djDebug #djDebugToolbar li.djdt-active a:hover {
color:#b36a60;
background-color:transparent;
}
#djDebug #djDebugToolbar li small {
font-size:12px;
color:#999;
font-style:normal;
text-decoration:none;
font-variant:small-caps;
}
#djDebug #djDebugToolbarHandle {
position:fixed;
background-color:#fff;
border:1px solid #111;
top:30px;
right:0;
z-index:100000000;
opacity:0.75;
}
#djDebug #djShowToolBarButton {
display:block;
height:75px;
width:30px;
border-right:none;
border-bottom:4px solid #fff;
border-top:4px solid #fff;
border-left:4px solid #fff;
color:#fff;
font-size:10px;
font-weight:bold;
text-decoration:none;
text-align:center;
text-indent:-999999px;
background: #000 no-repeat left center;
background-image: url(../img/djdt_vertical.png);
opacity:0.5;
}
#djDebug #djShowToolBarButton:hover {
background-color:#111;
border-top-color:#FFE761;
border-left-color:#FFE761;
border-bottom-color:#FFE761;
cursor:move;
opacity:1.0;
}
#djDebug code {
display:block;
font-family:Consolas, Monaco, "Bitstream Vera Sans Mono", "Lucida Console", monospace;
font-size: 12px;
white-space:pre;
overflow:auto;
}
#djDebug .djDebugOdd {
background-color:#f5f5f5;
}
#djDebug .djdt-panelContent {
display:none;
position:fixed;
margin:0;
top:0;
right:200px;
bottom:0;
left:0px;
background-color:#eee;
color:#666;
z-index:100000000;
}
#djDebug .djdt-panelContent > div {
border-bottom:1px solid #ddd;
}
#djDebug .djDebugPanelTitle {
position:absolute;
background-color:#ffc;
color:#666;
padding-left:20px;
top:0;
right:0;
left:0;
height:50px;
}
#djDebug .djDebugPanelTitle code {
display:inline;
font-size:inherit;
}
#djDebug .djDebugPanelContent {
position:absolute;
top:50px;
right:0;
bottom:0;
left:0;
height:auto;
padding:5px 0 0 20px;
}
#djDebug .djDebugPanelContent .djdt-loader {
display:block;
margin:80px auto;
}
#djDebug .djDebugPanelContent .djdt-scroll {
height:100%;
overflow:auto;
display:block;
padding:0 10px 0 0;
}
#djDebug h3 {
font-size:24px;
font-weight:normal;
line-height:50px;
}
#djDebug h4 {
font-size:20px;
font-weight:bold;
margin-top:0.8em;
}
#djDebug .djdt-panelContent table {
border:1px solid #ccc;
border-collapse:collapse;
width:100%;
background-color:#fff;
display:table;
margin-top:0.8em;
overflow: auto;
}
#djDebug .djdt-panelContent tbody td,
#djDebug .djdt-panelContent tbody th {
vertical-align:top;
padding:2px 3px;
}
#djDebug .djdt-panelContent tbody td.djdt-time {
text-align: center;
}
#djDebug .djdt-panelContent thead th {
padding:1px 6px 1px 3px;
text-align:left;
font-weight:bold;
font-size:14px;
white-space: nowrap;
}
#djDebug .djdt-panelContent tbody th {
width:12em;
text-align:right;
color:#666;
padding-right:.5em;
}
#djDebug .djTemplateContext {
background-color:#fff;
}
/*
#djDebug .djdt-panelContent p a:hover, #djDebug .djdt-panelContent dd a:hover {
color:#111;
background-color:#ffc;
}
#djDebug .djdt-panelContent p {
padding:0 5px;
}
#djDebug .djdt-panelContent p, #djDebug .djdt-panelContent table, #djDebug .djdt-panelContent ol, #djDebug .djdt-panelContent ul, #djDebug .djdt-panelContent dl {
margin:5px 0 15px;
background-color:#fff;
}
#djDebug .djdt-panelContent table {
clear:both;
border:0;
padding:0;
margin:0;
border-collapse:collapse;
border-spacing:0;
}
#djDebug .djdt-panelContent table a {
color:#000;
padding:2px 4px;
}
#djDebug .djdt-panelContent table a:hover {
background-color:#ffc;
}
#djDebug .djdt-panelContent table th {
background-color:#333;
font-weight:bold;
color:#fff;
padding:3px 7px 3px;
text-align:left;
cursor:pointer;
}
#djDebug .djdt-panelContent table td {
padding:5px 10px;
font-size:14px;
background-color:#fff;
color:#000;
vertical-align:top;
border:0;
}
#djDebug .djdt-panelContent table tr.djDebugOdd td {
background-color:#eee;
}
*/
#djDebug .djdt-panelContent .djDebugClose {
display:block;
position:absolute;
top:4px;
right:15px;
height:40px;
width:40px;
background: no-repeat center center;
background-image: url(../img/close.png);
}
#djDebug .djdt-panelContent .djDebugClose:hover {
background-image: url(../img/close_hover.png);
}
#djDebug .djdt-panelContent .djDebugClose.djDebugBack {
background-image: url(../img/back.png);
}
#djDebug .djdt-panelContent .djDebugClose.djDebugBack:hover {
background-image: url(../img/back_hover.png);
}
#djDebug .djdt-panelContent dt, #djDebug .djdt-panelContent dd {
display:block;
}
#djDebug .djdt-panelContent dt {
margin-top:0.75em;
}
#djDebug .djdt-panelContent dd {
margin-left:10px;
}
#djDebug a.toggleTemplate {
padding:4px;
background-color:#bbb;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
}
#djDebug a.toggleTemplate:hover {
padding:4px;
background-color:#444;
color:#ffe761;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
}
#djDebug .djDebugSqlWrap {
position:relative;
}
#djDebug .djDebugCollapsed {
display: none;
text-decoration: none;
color: #333;
}
#djDebug .djDebugUncollapsed {
color: #333;
text-decoration: none;
}
#djDebug .djUnselected {
display: none;
}
#djDebug tr.djHiddenByDefault {
display: none;
}
#djDebug tr.djSelected {
display: table-row;
}
#djDebug .djDebugSql {
word-break:break-word;
z-index:100000002;
}
#djDebug .djSQLDetailsDiv tbody th {
text-align: left;
}
#djDebug .djSqlExplain td {
white-space: pre;
}
#djDebug span.djDebugLineChart {
background-color:#777;
height:3px;
position:absolute;
bottom:0;
top:0;
left:0;
display:block;
z-index:1000000001;
}
#djDebug span.djDebugLineChartWarning {
background-color:#900;
}
#djDebug .highlight { color:#000; }
#djDebug .highlight .err { color:#000; } /* Error */
#djDebug .highlight .g { color:#000; } /* Generic */
#djDebug .highlight .k { color:#000; font-weight:bold } /* Keyword */
#djDebug .highlight .o { color:#000; } /* Operator */
#djDebug .highlight .n { color:#000; } /* Name */
#djDebug .highlight .mi { color:#000; font-weight:bold } /* Literal.Number.Integer */
#djDebug .highlight .l { color:#000; } /* Literal */
#djDebug .highlight .x { color:#000; } /* Other */
#djDebug .highlight .p { color:#000; } /* Punctuation */
#djDebug .highlight .m { color:#000; font-weight:bold } /* Literal.Number */
#djDebug .highlight .s { color:#333 } /* Literal.String */
#djDebug .highlight .w { color:#888888 } /* Text.Whitespace */
#djDebug .highlight .il { color:#000; font-weight:bold } /* Literal.Number.Integer.Long */
#djDebug .highlight .na { color:#333 } /* Name.Attribute */
#djDebug .highlight .nt { color:#000; font-weight:bold } /* Name.Tag */
#djDebug .highlight .nv { color:#333 } /* Name.Variable */
#djDebug .highlight .s2 { color:#333 } /* Literal.String.Double */
#djDebug .highlight .cp { color:#333 } /* Comment.Preproc */
#djDebug .djdt-timeline {
width: 30%;
}
#djDebug .djDebugTimeline {
position: relative;
height: 100%;
min-height: 100%;
}
#djDebug div.djDebugLineChart {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
vertical-align: middle;
}
#djDebug div.djDebugLineChart strong {
text-indent: -10000em;
display: block;
font-weight: normal;
vertical-align: middle;
background-color:#ccc;
}
#djDebug div.djDebugLineChartWarning strong {
background-color:#900;
}
#djDebug .djDebugInTransaction div.djDebugLineChart strong {
background-color: #d3ff82;
}
#djDebug .djDebugStartTransaction div.djDebugLineChart strong {
border-left: 1px solid #94b24d;
}
#djDebug .djDebugEndTransaction div.djDebugLineChart strong {
border-right: 1px solid #94b24d;
}
#djDebug .djdt-panelContent ul.djdt-stats {
position: relative;
list-style-type: none;
}
#djDebug .djdt-panelContent ul.djdt-stats li {
width: 30%;
float: left;
}
#djDebug .djdt-panelContent ul.djdt-stats li strong.djdt-label {
display: block;
}
#djDebug .djdt-panelContent ul.djdt-stats li span.djdt-color {
height: 12px;
width: 3px;
display: inline-block;
}
#djDebug .djdt-panelContent ul.djdt-stats li span.djdt-info {
display: block;
padding-left: 5px;
}
#djDebug .djdt-panelContent thead th {
white-space: nowrap;
}
#djDebug .djDebugRowWarning .djdt-time {
color: red;
}
#djdebug .djdt-panelContent table .djdt-toggle {
width: 14px;
padding-top: 3px;
}
#djDebug .djdt-panelContent table .djdt-actions {
min-width: 70px;
white-space: nowrap;
}
#djdebug .djdt-panelContent table .djdt-color {
width: 3px;
}
#djdebug .djdt-panelContent table .djdt-color span {
width: 3px;
height: 12px;
overflow: hidden;
padding: 0;
}
#djDebug .djToggleSwitch {
text-decoration: none;
border: 1px solid #999;
height: 12px;
width: 12px;
line-height: 12px;
text-align: center;
color: #777;
display: inline-block;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF', endColorstr='#DCDCDC'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#DCDCDC)); /* for webkit browsers */
background:-moz-linear-gradient(center top , #FFFFFF 0pt, #DCDCDC 100%) repeat scroll 0 0 transparent;
}
#djDebug .djNoToggleSwitch {
height: 14px;
width: 14px;
display: inline-block;
}
#djDebug .djSQLDetailsDiv {
margin-top:0.8em;
}
#djDebug pre {
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS-3 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
color: #555;
border:1px solid #ccc;
border-collapse:collapse;
background-color:#fff;
display:block;
overflow: auto;
padding:2px 3px;
margin-bottom: 3px;
font-family:Consolas, Monaco, "Bitstream Vera Sans Mono", "Lucida Console", monospace;
}
#djDebug .djdt-stack span {
color: #000;
font-weight: bold;
}
#djDebug .djdt-stack span.djdt-path,
#djDebug .djdt-stack pre.djdt-locals,
#djDebug .djdt-stack pre.djdt-locals span {
color: #777;
font-weight: normal;
}
#djDebug .djdt-stack span.djdt-code {
font-weight: normal;
}
#djDebug .djdt-stack pre.djdt-locals {
margin: 0 27px 27px 27px;
}
#djDebug .djdt-width-20 {
width: 20%;
}
#djDebug .djdt-width-60 {
width: 60%;
}
#djDebug .djdt-highlighted {
background-color: lightgrey;
}
.djdt-hidden {
display: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

View File

@ -0,0 +1 @@
document.getElementById('redirect_to').focus();

View File

@ -0,0 +1,324 @@
(function () {
var $$ = {
on: function(root, eventName, selector, fn) {
root.addEventListener(eventName, function(event) {
var target = event.target.closest(selector);
if (root.contains(target)) {
fn.call(target, event);
}
});
},
show: function(element) {
element.style.display = 'block';
},
hide: function(element) {
element.style.display = 'none';
},
toggle: function(element, value) {
if (value) {
$$.show(element);
} else {
$$.hide(element);
}
},
visible: function(element) {
style = getComputedStyle(element);
return style.display !== 'none';
},
executeScripts: function(root) {
root.querySelectorAll('script').forEach(function(e) {
var clone = document.createElement('script');
clone.src = e.src;
root.appendChild(clone);
});
},
};
var onKeyDown = function(event) {
if (event.keyCode == 27) {
djdt.hide_one_level();
}
};
var ajax = function(url, init) {
init = Object.assign({credentials: 'same-origin'}, init);
return fetch(url, init).then(function(response) {
if (response.ok) {
return response.text();
} else {
var win = document.querySelector('#djDebugWindow');
win.innerHTML = '<div class="djDebugPanelTitle"><a class="djDebugClose djDebugBack" href=""></a><h3>'+response.status+': '+response.statusText+'</h3></div>';
$$.show(win);
return Promise.reject();
}
});
};
var djdt = {
handleDragged: false,
events: {
ready: []
},
isReady: false,
init: function() {
var djDebug = document.querySelector('#djDebug');
$$.show(djDebug);
$$.on(djDebug.querySelector('#djDebugPanelList'), 'click', 'li a', function(event) {
event.preventDefault();
if (!this.className) {
return;
}
var current = djDebug.querySelector('#' + this.className);
if ($$.visible(current)) {
djdt.hide_panels();
} else {
djdt.hide_panels();
$$.show(current);
this.parentElement.classList.add('djdt-active');
var inner = current.querySelector('.djDebugPanelContent .djdt-scroll'),
store_id = djDebug.dataset.storeId;
if (store_id && inner.children.length === 0) {
var url = djDebug.dataset.renderPanelUrl;
var url_params = new URLSearchParams();
url_params.append('store_id', store_id);
url_params.append('panel_id', this.className);
url += '?' + url_params.toString();
ajax(url).then(function(body) {
inner.previousElementSibling.remove(); // Remove AJAX loader
inner.innerHTML = body;
$$.executeScripts(inner);
});
}
}
});
$$.on(djDebug, 'click', 'a.djDebugClose', function(event) {
event.preventDefault();
djdt.hide_one_level();
});
$$.on(djDebug, 'click', '.djDebugPanelButton input[type=checkbox]', function() {
djdt.cookie.set(this.dataset.cookie, this.checked ? 'on' : 'off', {
path: '/',
expires: 10
});
});
// Used by the SQL and template panels
$$.on(djDebug, 'click', '.remoteCall', function(event) {
event.preventDefault();
var name = this.tagName.toLowerCase();
var ajax_data = {};
if (name == 'button') {
var form = this.closest('form');
ajax_data.url = this.getAttribute('formaction');
if (form) {
ajax_data.body = new FormData(form);
ajax_data.method = form.getAttribute('method') || 'POST';
}
}
if (name == 'a') {
ajax_data.url = this.getAttribute('href');
}
ajax(ajax_data.url, ajax_data).then(function(body) {
var win = djDebug.querySelector('#djDebugWindow');
win.innerHTML = body;
$$.executeScripts(win);
$$.show(win);
});
});
// Used by the cache, profiling and SQL panels
$$.on(djDebug, 'click', 'a.djToggleSwitch', function(event) {
event.preventDefault();
var self = this;
var id = this.dataset.toggleId;
var open_me = this.textContent == this.dataset.toggleOpen;
if (id === '' || !id) {
return;
}
var name = this.dataset.toggleName;
var container = this.closest('.djDebugPanelContent').querySelector('#' + name + '_' + id);
container.querySelectorAll('.djDebugCollapsed').forEach(function(e) {
$$.toggle(e, open_me);
});
container.querySelectorAll('.djDebugUncollapsed').forEach(function(e) {
$$.toggle(e, !open_me);
});
this.closest('.djDebugPanelContent').querySelectorAll('.djToggleDetails_' + id).forEach(function(e) {
if (open_me) {
e.classList.add('djSelected');
e.classList.remove('djUnselected');
self.textContent = self.dataset.toggleClose;
} else {
e.classList.remove('djSelected');
e.classList.add('djUnselected');
self.textContent = self.dataset.toggleOpen;
}
var switch_ = e.querySelector('.djToggleSwitch')
if (switch_) switch_.textContent = self.textContent;
});
});
djDebug.querySelector('#djHideToolBarButton').addEventListener('click', function(event) {
event.preventDefault();
djdt.hide_toolbar(true);
});
djDebug.querySelector('#djShowToolBarButton').addEventListener('click', function(event) {
event.preventDefault();
if (!djdt.handleDragged) {
djdt.show_toolbar();
}
});
var startPageY, baseY;
var handle = document.querySelector('#djDebugToolbarHandle');
var onHandleMove = function(event) {
// Chrome can send spurious mousemove events, so don't do anything unless the
// cursor really moved. Otherwise, it will be impossible to expand the toolbar
// due to djdt.handleDragged being set to true.
if (djdt.handleDragged || event.pageY != startPageY) {
var top = baseY + event.pageY;
if (top < 0) {
top = 0;
} else if (top + handle.offsetHeight > window.innerHeight) {
top = window.innerHeight - handle.offsetHeight;
}
handle.style.top = top + 'px';
djdt.handleDragged = true;
}
};
djDebug.querySelector('#djShowToolBarButton').addEventListener('mousedown', function(event) {
event.preventDefault();
startPageY = event.pageY;
baseY = handle.offsetTop - startPageY;
document.addEventListener('mousemove', onHandleMove);
});
document.addEventListener('mouseup', function (event) {
document.removeEventListener('mousemove', onHandleMove);
if (djdt.handleDragged) {
event.preventDefault();
djdt.cookie.set('djdttop', handle.offsetTop, {
path: '/',
expires: 10
});
setTimeout(function () {
djdt.handleDragged = false;
}, 10);
}
});
if (djdt.cookie.get('djdt') == 'hide') {
djdt.hide_toolbar(false);
} else {
djdt.show_toolbar();
}
djdt.isReady = true;
djdt.events.ready.forEach(function(callback) {
callback(djdt);
});
},
hide_panels: function() {
$$.hide(djDebug.querySelector('#djDebugWindow'));
djDebug.querySelectorAll('.djdt-panelContent').forEach(function(e) {
$$.hide(e);
});
djDebug.querySelectorAll('#djDebugToolbar li').forEach(function(e) {
e.classList.remove('djdt-active');
});
},
hide_toolbar: function(setCookie) {
djdt.hide_panels();
$$.hide(djDebug.querySelector('#djDebugToolbar'));
var handle = document.querySelector('#djDebugToolbarHandle');
$$.show(handle);
// set handle position
var handleTop = djdt.cookie.get('djdttop');
if (handleTop) {
handleTop = Math.min(handleTop, window.innerHeight - handle.offsetHeight);
handle.style.top = handleTop + 'px';
}
document.removeEventListener('keydown', onKeyDown);
if (setCookie) {
djdt.cookie.set('djdt', 'hide', {
path: '/',
expires: 10
});
}
},
hide_one_level: function(skipDebugWindow) {
if ($$.visible(djDebug.querySelector('#djDebugWindow'))) {
$$.hide(djDebug.querySelector('#djDebugWindow'));
} else if (djDebug.querySelector('#djDebugToolbar li.djdt-active')) {
djdt.hide_panels();
} else {
djdt.hide_toolbar(true);
}
},
show_toolbar: function() {
document.addEventListener('keydown', onKeyDown);
$$.hide(djDebug.querySelector('#djDebugToolbarHandle'));
$$.show(djDebug.querySelector('#djDebugToolbar'));
djdt.cookie.set('djdt', 'show', {
path: '/',
expires: 10
});
},
ready: function(callback){
if (djdt.isReady) {
callback(djdt);
} else {
djdt.events.ready.push(callback);
}
},
cookie: {
get: function(key){
if (document.cookie.indexOf(key) === -1) return null;
var cookieArray = document.cookie.split('; '),
cookies = {};
cookieArray.forEach(function(e){
var parts = e.split('=');
cookies[ parts[0] ] = parts[1];
});
return cookies[ key ];
},
set: function(key, value, options){
options = options || {};
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
document.cookie = [
encodeURIComponent(key) + '=' + String(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '',
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join('');
return value;
}
},
};
window.djdt = {
show_toolbar: djdt.show_toolbar,
hide_toolbar: djdt.hide_toolbar,
init: djdt.init,
close: djdt.hide_one_level,
cookie: djdt.cookie,
};
document.addEventListener('DOMContentLoaded', djdt.init);
})();

View File

@ -0,0 +1,52 @@
(function () {
// Browser timing remains hidden unless we can successfully access the performance object
var perf = window.performance || window.msPerformance ||
window.webkitPerformance || window.mozPerformance;
if (!perf)
return;
var rowCount = 0,
timingOffset = perf.timing.navigationStart,
timingEnd = perf.timing.loadEventEnd,
totalTime = timingEnd - timingOffset;
function getLeft(stat) {
return ((perf.timing[stat] - timingOffset) / (totalTime)) * 100.0;
}
function getCSSWidth(stat, endStat) {
var width = ((perf.timing[endStat] - perf.timing[stat]) / (totalTime)) * 100.0;
// Calculate relative percent (same as sql panel logic)
width = 100.0 * width / (100.0 - getLeft(stat));
return (width < 1) ? "2px" : width + "%";
}
function addRow(stat, endStat) {
rowCount++;
var row = document.createElement('tr');
row.className = (rowCount % 2) ? 'djDebugOdd' : 'djDebugEven';
if (endStat) {
// Render a start through end bar
row.innerHTML = '<td>' + stat.replace('Start', '') + '</td>' +
'<td class="djdt-timeline"><div class="djDebugTimeline"><div class="djDebugLineChart"><strong>&#160;</strong></div></div></td>' +
'<td>' + (perf.timing[stat] - timingOffset) + ' (+' + (perf.timing[endStat] - perf.timing[stat]) + ')</td>';
row.querySelector('strong').style.width = getCSSWidth(stat, endStat);
} else {
// Render a point in time
row.innerHTML = '<td>' + stat + '</td>' +
'<td class="djdt-timeline"><div class="djDebugTimeline"><div class="djDebugLineChart"><strong>&#160;</strong></div></div></td>' +
'<td>' + (perf.timing[stat] - timingOffset) + '</td>';
row.querySelector('strong').style.width = '2px';
}
row.querySelector('.djDebugLineChart').style.left = getLeft(stat) + '%';
document.querySelector('#djDebugBrowserTimingTableBody').appendChild(row);
}
// This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param)
addRow('domainLookupStart', 'domainLookupEnd');
addRow('connectStart', 'connectEnd');
addRow('requestStart', 'responseEnd'); // There is no requestEnd
addRow('responseStart', 'responseEnd');
addRow('domLoading', 'domComplete'); // Spans the events below
addRow('domInteractive');
addRow('domContentLoadedEventStart', 'domContentLoadedEventEnd');
addRow('loadEventStart', 'loadEventEnd');
document.querySelector('#djDebugBrowserTiming').classList.remove('djdt-hidden');
})();

View File

@ -98,7 +98,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="nav-link" href="{% url 'note:transfer' %}"><i class="fas fa-exchange-alt"></i>{% trans 'Transfer' %} </a>
</li>
{% endif %}
{% if "auth.user"|model_list|length >= 2 %}
{% if "auth.user"|model_list_length >= 2 %}
<li class="nav-item active">
<a class="nav-link" href="{% url 'member:user_list' %}"><i class="fas fa-user"></i> {% trans 'Users' %}</a>
</li>

View File

@ -68,15 +68,15 @@
<div class="card shadow mb-4">
<div class="card-header">
<p class="card-text font-weight-bold">
{% trans "Most used buttons" %}
{% trans "Highlighted buttons" %}
</p>
</div>
<div class="card-body text-nowrap" style="overflow:auto hidden">
<div class="d-inline-flex flex-wrap justify-content-center" id="most_used">
{% for button in most_used %}
<div class="d-inline-flex flex-wrap justify-content-center" id="highlighted">
{% for button in highlighted %}
{% if button.display %}
<button class="btn btn-outline-dark rounded-0 flex-fill"
id="most_used_button{{ button.id }}" name="button" value="{{ button.name }}">
id="highlighted_button{{ button.id }}" name="button" value="{{ button.name }}">
{{ button.name }} ({{ button.amount | pretty_money }})
</button>
{% endif %}
@ -86,7 +86,7 @@
</div>
{# Regroup buttons under categories #}
{% regroup transaction_templates by category as categories %}
{# {% regroup transaction_templates by category as categories %} #}
<div class="card border-primary text-center shadow mb-4">
{# Tabs for button categories #}
@ -94,8 +94,8 @@
<ul class="nav nav-tabs nav-fill card-header-tabs">
{% for category in categories %}
<li class="nav-item">
<a class="nav-link font-weight-bold" data-toggle="tab" href="#{{ category.grouper|slugify }}">
{{ category.grouper }}
<a class="nav-link font-weight-bold" data-toggle="tab" href="#{{ category.name|slugify }}">
{{ category.name }}
</a>
</li>
{% endfor %}
@ -106,9 +106,9 @@
<div class="card-body">
<div class="tab-content">
{% for category in categories %}
<div class="tab-pane" id="{{ category.grouper|slugify }}">
<div class="tab-pane" id="{{ category.name|slugify }}">
<div class="d-inline-flex flex-wrap justify-content-center">
{% for button in category.list %}
{% for button in category.templates_filtered %}
{% if button.display %}
<button class="btn btn-outline-dark rounded-0 flex-fill"
id="button{{ button.id }}" name="button" value="{{ button.name }}">
@ -157,24 +157,26 @@
{% block extrajavascript %}
<script type="text/javascript" src="{% static "js/consos.js" %}"></script>
<script type="text/javascript">
{% for button in most_used %}
{% for button in highlighted %}
{% if button.display %}
$("#most_used_button{{ button.id }}").click(function() {
addConso({{ button.destination.id }}, {{ button.amount }},
{{ polymorphic_ctype }}, {{ button.category.id }}, "{{ button.category.name }}",
$("#highlighted_button{{ button.id }}").click(function() {
addConso({{ button.destination_id }}, {{ button.amount }},
{{ polymorphic_ctype }}, {{ button.category_id }}, "{{ button.category.name }}",
{{ button.id }}, "{{ button.name }}");
});
{% endif %}
{% endfor %}
{% for button in transaction_templates %}
{% for category in categories %}
{% for button in category.templates_filtered %}
{% if button.display %}
$("#button{{ button.id }}").click(function() {
addConso({{ button.destination.id }}, {{ button.amount }},
{{ polymorphic_ctype }}, {{ button.category.id }}, "{{ button.category.name }}",
addConso({{ button.destination_id }}, {{ button.amount }},
{{ polymorphic_ctype }}, {{ button.category_id }}, "{{ button.category.name }}",
{{ button.id }}, "{{ button.name }}");
});
{% endif %}
{% endfor %}
{% endfor %}
</script>
{% endblock %}

View File

@ -55,5 +55,11 @@
<hr>
<h2>{% trans "Closed remittances" %}</h2>
{% if closed_remittances.data %}
{% render_table closed_remittances %}
{% else %}
<div class="alert alert-warning">
{% trans "There is no closed remittance yet." %}
</div>
{% endif %}
{% endblock %}