mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-26 02:54:20 +00:00
Merge pull request #714 from ae-utbm/taiste
More ruff rules, mistune update and more bot-blocking features
This commit is contained in:
commit
b852176958
@ -1,7 +1,7 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
# Ruff version.
|
# Ruff version.
|
||||||
rev: v0.4.10
|
rev: v0.5.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff # just check the code, and print the errors
|
- id: ruff # just check the code, and print the errors
|
||||||
- id: ruff # actually fix the fixable errors, but print nothing
|
- id: ruff # actually fix the fixable errors, but print nothing
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@ -101,6 +100,6 @@ class Migration(migrations.Migration):
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="operation", unique_together=set([("number", "journal")])
|
name="operation", unique_together={("number", "journal")}
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import phonenumber_field.modelfields
|
import phonenumber_field.modelfields
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@ -46,6 +45,6 @@ class Migration(migrations.Migration):
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="label", unique_together=set([("name", "club_account")])
|
name="label", unique_together={("name", "club_account")}
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -37,11 +36,11 @@ class CurrencyField(models.DecimalField):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs["max_digits"] = 12
|
kwargs["max_digits"] = 12
|
||||||
kwargs["decimal_places"] = 2
|
kwargs["decimal_places"] = 2
|
||||||
super(CurrencyField, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
try:
|
try:
|
||||||
return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01"))
|
return super().to_python(value).quantize(Decimal("0.01"))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -62,6 +61,15 @@ class Company(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("company")
|
verbose_name = _("company")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
|
||||||
|
|
||||||
|
def get_display_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -88,15 +96,6 @@ class Company(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
|
|
||||||
|
|
||||||
def get_display_name(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class BankAccount(models.Model):
|
class BankAccount(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=30)
|
name = models.CharField(_("name"), max_length=30)
|
||||||
@ -113,6 +112,12 @@ class BankAccount(models.Model):
|
|||||||
verbose_name = _("Bank account")
|
verbose_name = _("Bank account")
|
||||||
ordering = ["club", "name"]
|
ordering = ["club", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -126,12 +131,6 @@ class BankAccount(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class ClubAccount(models.Model):
|
class ClubAccount(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=30)
|
name = models.CharField(_("name"), max_length=30)
|
||||||
@ -152,6 +151,12 @@ class ClubAccount(models.Model):
|
|||||||
verbose_name = _("Club account")
|
verbose_name = _("Club account")
|
||||||
ordering = ["bank_account", "name"]
|
ordering = ["bank_account", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -189,12 +194,6 @@ class ClubAccount(models.Model):
|
|||||||
def get_open_journal(self):
|
def get_open_journal(self):
|
||||||
return self.journals.filter(closed=False).first()
|
return self.journals.filter(closed=False).first()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_display_name(self):
|
def get_display_name(self):
|
||||||
return _("%(club_account)s on %(bank_account)s") % {
|
return _("%(club_account)s on %(bank_account)s") % {
|
||||||
"club_account": self.name,
|
"club_account": self.name,
|
||||||
@ -225,6 +224,12 @@ class GeneralJournal(models.Model):
|
|||||||
verbose_name = _("General journal")
|
verbose_name = _("General journal")
|
||||||
ordering = ["-start_date"]
|
ordering = ["-start_date"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -250,12 +255,6 @@ class GeneralJournal(models.Model):
|
|||||||
def can_be_viewed_by(self, user):
|
def can_be_viewed_by(self, user):
|
||||||
return self.club_account.can_be_viewed_by(user)
|
return self.club_account.can_be_viewed_by(user)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def update_amounts(self):
|
def update_amounts(self):
|
||||||
self.amount = 0
|
self.amount = 0
|
||||||
self.effective_amount = 0
|
self.effective_amount = 0
|
||||||
@ -357,6 +356,18 @@ class Operation(models.Model):
|
|||||||
unique_together = ("number", "journal")
|
unique_together = ("number", "journal")
|
||||||
ordering = ["-number"]
|
ordering = ["-number"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.amount} € | {self.date} | {self.accounting_type} | {self.done}"
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.number is None:
|
||||||
|
self.number = self.journal.operations.count() + 1
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
self.journal.update_amounts()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
|
||||||
|
|
||||||
def __getattribute__(self, attr):
|
def __getattribute__(self, attr):
|
||||||
if attr == "target":
|
if attr == "target":
|
||||||
return self.get_target()
|
return self.get_target()
|
||||||
@ -364,7 +375,7 @@ class Operation(models.Model):
|
|||||||
return object.__getattribute__(self, attr)
|
return object.__getattribute__(self, attr)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super(Operation, self).clean()
|
super().clean()
|
||||||
if self.date is None:
|
if self.date is None:
|
||||||
raise ValidationError(_("The date must be set."))
|
raise ValidationError(_("The date must be set."))
|
||||||
elif self.date < self.journal.start_date:
|
elif self.date < self.journal.start_date:
|
||||||
@ -410,12 +421,6 @@ class Operation(models.Model):
|
|||||||
tar = Company.objects.filter(id=self.target_id).first()
|
tar = Company.objects.filter(id=self.target_id).first()
|
||||||
return tar
|
return tar
|
||||||
|
|
||||||
def save(self):
|
|
||||||
if self.number is None:
|
|
||||||
self.number = self.journal.operations.count() + 1
|
|
||||||
super(Operation, self).save()
|
|
||||||
self.journal.update_amounts()
|
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -444,17 +449,6 @@ class Operation(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%d € | %s | %s | %s" % (
|
|
||||||
self.amount,
|
|
||||||
self.date,
|
|
||||||
self.accounting_type,
|
|
||||||
self.done,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AccountingType(models.Model):
|
class AccountingType(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -487,6 +481,12 @@ class AccountingType(models.Model):
|
|||||||
verbose_name = _("accounting type")
|
verbose_name = _("accounting type")
|
||||||
ordering = ["movement_type", "code"]
|
ordering = ["movement_type", "code"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:type_list")
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -497,12 +497,6 @@ class AccountingType(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:type_list")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
|
|
||||||
|
|
||||||
|
|
||||||
class SimplifiedAccountingType(models.Model):
|
class SimplifiedAccountingType(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -521,6 +515,15 @@ class SimplifiedAccountingType(models.Model):
|
|||||||
verbose_name = _("simplified type")
|
verbose_name = _("simplified type")
|
||||||
ordering = ["accounting_type__movement_type", "accounting_type__code"]
|
ordering = ["accounting_type__movement_type", "accounting_type__code"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"{self.get_movement_type_display()} "
|
||||||
|
f"- {self.accounting_type.code} - {self.label}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:simple_type_list")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def movement_type(self):
|
def movement_type(self):
|
||||||
return self.accounting_type.movement_type
|
return self.accounting_type.movement_type
|
||||||
@ -528,18 +531,6 @@ class SimplifiedAccountingType(models.Model):
|
|||||||
def get_movement_type_display(self):
|
def get_movement_type_display(self):
|
||||||
return self.accounting_type.get_movement_type_display()
|
return self.accounting_type.get_movement_type_display()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:simple_type_list")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return (
|
|
||||||
self.get_movement_type_display()
|
|
||||||
+ " - "
|
|
||||||
+ self.accounting_type.code
|
|
||||||
+ " - "
|
|
||||||
+ self.label
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Label(models.Model):
|
class Label(models.Model):
|
||||||
"""Label allow a club to sort its operations"""
|
"""Label allow a club to sort its operations"""
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -210,7 +209,7 @@ class ClubAccountCreateView(CanCreateMixin, CreateView):
|
|||||||
template_name = "core/create.jinja"
|
template_name = "core/create.jinja"
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
ret = super(ClubAccountCreateView, self).get_initial()
|
ret = super().get_initial()
|
||||||
if "parent" in self.request.GET.keys():
|
if "parent" in self.request.GET.keys():
|
||||||
obj = BankAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
obj = BankAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
@ -296,7 +295,7 @@ class JournalCreateView(CanCreateMixin, CreateView):
|
|||||||
template_name = "core/create.jinja"
|
template_name = "core/create.jinja"
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
ret = super(JournalCreateView, self).get_initial()
|
ret = super().get_initial()
|
||||||
if "parent" in self.request.GET.keys():
|
if "parent" in self.request.GET.keys():
|
||||||
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
@ -339,7 +338,7 @@ class JournalDeleteView(CanEditPropMixin, DeleteView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
if self.object.operations.count() == 0:
|
if self.object.operations.count() == 0:
|
||||||
return super(JournalDeleteView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
@ -387,7 +386,7 @@ class OperationForm(forms.ModelForm):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
club_account = kwargs.pop("club_account", None)
|
club_account = kwargs.pop("club_account", None)
|
||||||
super(OperationForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
if club_account:
|
if club_account:
|
||||||
self.fields["label"].queryset = club_account.labels.order_by("name").all()
|
self.fields["label"].queryset = club_account.labels.order_by("name").all()
|
||||||
if self.instance.target_type == "USER":
|
if self.instance.target_type == "USER":
|
||||||
@ -400,7 +399,7 @@ class OperationForm(forms.ModelForm):
|
|||||||
self.fields["company"].initial = self.instance.target_id
|
self.fields["company"].initial = self.instance.target_id
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.cleaned_data = super(OperationForm, self).clean()
|
self.cleaned_data = super().clean()
|
||||||
if "target_type" in self.cleaned_data.keys():
|
if "target_type" in self.cleaned_data.keys():
|
||||||
if (
|
if (
|
||||||
self.cleaned_data.get("user") is None
|
self.cleaned_data.get("user") is None
|
||||||
@ -430,7 +429,7 @@ class OperationForm(forms.ModelForm):
|
|||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
ret = super(OperationForm, self).save()
|
ret = super().save()
|
||||||
if (
|
if (
|
||||||
self.instance.target_type == "ACCOUNT"
|
self.instance.target_type == "ACCOUNT"
|
||||||
and not self.instance.linked_operation
|
and not self.instance.linked_operation
|
||||||
@ -482,14 +481,14 @@ class OperationCreateView(CanCreateMixin, CreateView):
|
|||||||
return self.form_class(club_account=ca, **self.get_form_kwargs())
|
return self.form_class(club_account=ca, **self.get_form_kwargs())
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
ret = super(OperationCreateView, self).get_initial()
|
ret = super().get_initial()
|
||||||
if self.journal is not None:
|
if self.journal is not None:
|
||||||
ret["journal"] = self.journal.id
|
ret["journal"] = self.journal.id
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add journal to the context"""
|
"""Add journal to the context"""
|
||||||
kwargs = super(OperationCreateView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
if self.journal:
|
if self.journal:
|
||||||
kwargs["object"] = self.journal
|
kwargs["object"] = self.journal
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -507,7 +506,7 @@ class OperationEditView(CanEditMixin, UpdateView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add journal to the context"""
|
"""Add journal to the context"""
|
||||||
kwargs = super(OperationEditView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["object"] = self.object.journal
|
kwargs["object"] = self.object.journal
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -683,16 +682,16 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView):
|
|||||||
for sat in [None] + list(
|
for sat in [None] + list(
|
||||||
SimplifiedAccountingType.objects.order_by("label").all()
|
SimplifiedAccountingType.objects.order_by("label").all()
|
||||||
):
|
):
|
||||||
sum = queryset.filter(
|
amount = queryset.filter(
|
||||||
accounting_type__movement_type=movement_type, simpleaccounting_type=sat
|
accounting_type__movement_type=movement_type, simpleaccounting_type=sat
|
||||||
).aggregate(amount_sum=Sum("amount"))["amount_sum"]
|
).aggregate(amount_sum=Sum("amount"))["amount_sum"]
|
||||||
if sat:
|
if sat:
|
||||||
sat = sat.label
|
sat = sat.label
|
||||||
else:
|
else:
|
||||||
sat = ""
|
sat = ""
|
||||||
if sum:
|
if amount:
|
||||||
total_sum += sum
|
total_sum += amount
|
||||||
statement[sat] = sum
|
statement[sat] = amount
|
||||||
ret[movement_type] = statement
|
ret[movement_type] = statement
|
||||||
ret[movement_type + "_sum"] = total_sum
|
ret[movement_type + "_sum"] = total_sum
|
||||||
return ret
|
return ret
|
||||||
@ -728,7 +727,7 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add infos to the context"""
|
"""Add infos to the context"""
|
||||||
kwargs = super(JournalNatureStatementView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["statement"] = self.big_statement()
|
kwargs["statement"] = self.big_statement()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -767,7 +766,7 @@ class JournalPersonStatementView(JournalTabsMixin, CanViewMixin, DetailView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add journal to the context"""
|
"""Add journal to the context"""
|
||||||
kwargs = super(JournalPersonStatementView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["credit_statement"] = self.statement("CREDIT")
|
kwargs["credit_statement"] = self.statement("CREDIT")
|
||||||
kwargs["debit_statement"] = self.statement("DEBIT")
|
kwargs["debit_statement"] = self.statement("DEBIT")
|
||||||
kwargs["total_credit"] = self.total("CREDIT")
|
kwargs["total_credit"] = self.total("CREDIT")
|
||||||
@ -797,7 +796,7 @@ class JournalAccountingStatementView(JournalTabsMixin, CanViewMixin, DetailView)
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add journal to the context"""
|
"""Add journal to the context"""
|
||||||
kwargs = super(JournalAccountingStatementView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["statement"] = self.statement()
|
kwargs["statement"] = self.statement()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -852,7 +851,7 @@ class LabelCreateView(
|
|||||||
template_name = "core/create.jinja"
|
template_name = "core/create.jinja"
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
ret = super(LabelCreateView, self).get_initial()
|
ret = super().get_initial()
|
||||||
if "parent" in self.request.GET.keys():
|
if "parent" in self.request.GET.keys():
|
||||||
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
@ -897,19 +896,19 @@ class RefoundAccountView(FormView):
|
|||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
def dispatch(self, request, *arg, **kwargs):
|
def dispatch(self, request, *arg, **kwargs):
|
||||||
res = super(RefoundAccountView, self).dispatch(request, *arg, **kwargs)
|
res = super().dispatch(request, *arg, **kwargs)
|
||||||
if self.permission(request.user):
|
if self.permission(request.user):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def post(self, request, *arg, **kwargs):
|
def post(self, request, *arg, **kwargs):
|
||||||
self.operator = request.user
|
self.operator = request.user
|
||||||
if self.permission(request.user):
|
if self.permission(request.user):
|
||||||
return super(RefoundAccountView, self).post(self, request, *arg, **kwargs)
|
return super().post(self, request, *arg, **kwargs)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.customer = form.cleaned_data["user"]
|
self.customer = form.cleaned_data["user"]
|
||||||
self.create_selling()
|
self.create_selling()
|
||||||
return super(RefoundAccountView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse("accounting:refound_account")
|
return reverse("accounting:refound_account")
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -50,7 +49,7 @@ class ManageModelMixin:
|
|||||||
|
|
||||||
class RightModelViewSet(ManageModelMixin, viewsets.ModelViewSet):
|
class RightModelViewSet(ManageModelMixin, viewsets.ModelViewSet):
|
||||||
def dispatch(self, request, *arg, **kwargs):
|
def dispatch(self, request, *arg, **kwargs):
|
||||||
res = super(RightModelViewSet, self).dispatch(request, *arg, **kwargs)
|
res = super().dispatch(request, *arg, **kwargs)
|
||||||
obj = self.queryset
|
obj = self.queryset
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
try:
|
try:
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
@ -40,7 +39,7 @@ class ClubEditForm(forms.ModelForm):
|
|||||||
fields = ["address", "logo", "short_description"]
|
fields = ["address", "logo", "short_description"]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ClubEditForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["short_description"].widget = forms.Textarea()
|
self.fields["short_description"].widget = forms.Textarea()
|
||||||
|
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ class MailingForm(forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, club_id, user_id, mailings, *args, **kwargs):
|
def __init__(self, club_id, user_id, mailings, *args, **kwargs):
|
||||||
super(MailingForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
self.fields["action"] = forms.TypedChoiceField(
|
self.fields["action"] = forms.TypedChoiceField(
|
||||||
choices=(
|
choices=(
|
||||||
@ -116,7 +115,7 @@ class MailingForm(forms.Form):
|
|||||||
"""
|
"""
|
||||||
Convert given users into real users and check their validity
|
Convert given users into real users and check their validity
|
||||||
"""
|
"""
|
||||||
cleaned_data = super(MailingForm, self).clean()
|
cleaned_data = super().clean()
|
||||||
users = []
|
users = []
|
||||||
for user in cleaned_data["subscription_users"]:
|
for user in cleaned_data["subscription_users"]:
|
||||||
user = User.objects.filter(id=user).first()
|
user = User.objects.filter(id=user).first()
|
||||||
@ -133,7 +132,7 @@ class MailingForm(forms.Form):
|
|||||||
return users
|
return users
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(MailingForm, self).clean()
|
cleaned_data = super().clean()
|
||||||
|
|
||||||
if not "action" in cleaned_data:
|
if not "action" in cleaned_data:
|
||||||
# If there is no action provided, we can stop here
|
# If there is no action provided, we can stop here
|
||||||
@ -164,7 +163,7 @@ class SellingsForm(forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, club, *args, **kwargs):
|
def __init__(self, club, *args, **kwargs):
|
||||||
super(SellingsForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["products"] = forms.ModelMultipleChoiceField(
|
self.fields["products"] = forms.ModelMultipleChoiceField(
|
||||||
club.products.order_by("name").filter(archived=False).all(),
|
club.products.order_by("name").filter(archived=False).all(),
|
||||||
label=_("Products"),
|
label=_("Products"),
|
||||||
@ -201,7 +200,7 @@ class ClubMemberForm(forms.Form):
|
|||||||
self.club.members.filter(end_date=None).order_by("-role").all()
|
self.club.members.filter(end_date=None).order_by("-role").all()
|
||||||
)
|
)
|
||||||
self.request_user_membership = self.club.get_membership_for(self.request_user)
|
self.request_user_membership = self.club.get_membership_for(self.request_user)
|
||||||
super(ClubMemberForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
# Using a ModelForm binds too much the form with the model and we don't want that
|
# Using a ModelForm binds too much the form with the model and we don't want that
|
||||||
# We want the view to process the model creation since they are multiple users
|
# We want the view to process the model creation since they are multiple users
|
||||||
@ -241,7 +240,7 @@ class ClubMemberForm(forms.Form):
|
|||||||
Check that the user is not trying to add an user already in the club
|
Check that the user is not trying to add an user already in the club
|
||||||
Also check that the user is valid and has a valid subscription
|
Also check that the user is valid and has a valid subscription
|
||||||
"""
|
"""
|
||||||
cleaned_data = super(ClubMemberForm, self).clean()
|
cleaned_data = super().clean()
|
||||||
users = []
|
users = []
|
||||||
for user_id in cleaned_data["users"]:
|
for user_id in cleaned_data["users"]:
|
||||||
user = User.objects.filter(id=user_id).first()
|
user = User.objects.filter(id=user_id).first()
|
||||||
@ -264,7 +263,7 @@ class ClubMemberForm(forms.Form):
|
|||||||
"""
|
"""
|
||||||
Check user rights for adding an user
|
Check user rights for adding an user
|
||||||
"""
|
"""
|
||||||
cleaned_data = super(ClubMemberForm, self).clean()
|
cleaned_data = super().clean()
|
||||||
|
|
||||||
if "start_date" in cleaned_data and not cleaned_data["start_date"]:
|
if "start_date" in cleaned_data and not cleaned_data["start_date"]:
|
||||||
# Drop start_date if allowed to edition but not specified
|
# Drop start_date if allowed to edition but not specified
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@ -110,6 +109,6 @@ class Migration(migrations.Migration):
|
|||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="mailingsubscription",
|
name="mailingsubscription",
|
||||||
unique_together=set([("user", "email", "mailing")]),
|
unique_together={("user", "email", "mailing")},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@ -16,7 +15,7 @@ class Migration(migrations.Migration):
|
|||||||
name="owner_group",
|
name="owner_group",
|
||||||
field=models.ForeignKey(
|
field=models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
default=club.models.Club.get_default_owner_group,
|
default=club.models.get_default_owner_group,
|
||||||
related_name="owned_club",
|
related_name="owned_club",
|
||||||
to="core.Group",
|
to="core.Group",
|
||||||
),
|
),
|
||||||
|
147
club/models.py
147
club/models.py
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
@ -41,6 +40,11 @@ from core.models import Group, MetaGroup, Notification, Page, RealGroup, SithFil
|
|||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
|
||||||
|
# This function prevents generating migration upon settings change
|
||||||
|
def get_default_owner_group():
|
||||||
|
return settings.SITH_GROUP_ROOT_ID
|
||||||
|
|
||||||
|
|
||||||
class Club(models.Model):
|
class Club(models.Model):
|
||||||
"""
|
"""
|
||||||
The Club class, made as a tree to allow nice tidy organization
|
The Club class, made as a tree to allow nice tidy organization
|
||||||
@ -75,10 +79,6 @@ class Club(models.Model):
|
|||||||
)
|
)
|
||||||
address = models.CharField(_("address"), max_length=254)
|
address = models.CharField(_("address"), max_length=254)
|
||||||
|
|
||||||
# This function prevents generating migration upon settings change
|
|
||||||
def get_default_owner_group():
|
|
||||||
return settings.SITH_GROUP_ROOT_ID
|
|
||||||
|
|
||||||
owner_group = models.ForeignKey(
|
owner_group = models.ForeignKey(
|
||||||
Group,
|
Group,
|
||||||
related_name="owned_club",
|
related_name="owned_club",
|
||||||
@ -106,6 +106,34 @@ class Club(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["name", "unix_name"]
|
ordering = ["name", "unix_name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
old = Club.objects.filter(id=self.id).first()
|
||||||
|
creation = old is None
|
||||||
|
if not creation and old.unix_name != self.unix_name:
|
||||||
|
self._change_unixname(self.unix_name)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
if creation:
|
||||||
|
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
|
||||||
|
board.save()
|
||||||
|
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
|
||||||
|
member.save()
|
||||||
|
subscribers = Group.objects.filter(
|
||||||
|
name=settings.SITH_MAIN_MEMBERS_GROUP
|
||||||
|
).first()
|
||||||
|
self.make_home()
|
||||||
|
self.home.edit_groups.set([board])
|
||||||
|
self.home.view_groups.set([member, subscribers])
|
||||||
|
self.home.save()
|
||||||
|
self.make_page()
|
||||||
|
cache.set(f"sith_club_{self.unix_name}", self)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("club:club_view", kwargs={"club_id": self.id})
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def president(self):
|
def president(self):
|
||||||
return self.members.filter(
|
return self.members.filter(
|
||||||
@ -184,28 +212,6 @@ class Club(models.Model):
|
|||||||
self.page.parent = self.parent.page
|
self.page.parent = self.parent.page
|
||||||
self.page.save(force_lock=True)
|
self.page.save(force_lock=True)
|
||||||
|
|
||||||
@transaction.atomic()
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
old = Club.objects.filter(id=self.id).first()
|
|
||||||
creation = old is None
|
|
||||||
if not creation and old.unix_name != self.unix_name:
|
|
||||||
self._change_unixname(self.unix_name)
|
|
||||||
super(Club, self).save(*args, **kwargs)
|
|
||||||
if creation:
|
|
||||||
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
|
|
||||||
board.save()
|
|
||||||
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
|
|
||||||
member.save()
|
|
||||||
subscribers = Group.objects.filter(
|
|
||||||
name=settings.SITH_MAIN_MEMBERS_GROUP
|
|
||||||
).first()
|
|
||||||
self.make_home()
|
|
||||||
self.home.edit_groups.set([board])
|
|
||||||
self.home.view_groups.set([member, subscribers])
|
|
||||||
self.home.save()
|
|
||||||
self.make_page()
|
|
||||||
cache.set(f"sith_club_{self.unix_name}", self)
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
# Invalidate the cache of this club and of its memberships
|
# Invalidate the cache of this club and of its memberships
|
||||||
for membership in self.members.ongoing().select_related("user"):
|
for membership in self.members.ongoing().select_related("user"):
|
||||||
@ -213,12 +219,6 @@ class Club(models.Model):
|
|||||||
cache.delete(f"sith_club_{self.unix_name}")
|
cache.delete(f"sith_club_{self.unix_name}")
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("club:club_view", kwargs={"club_id": self.id})
|
|
||||||
|
|
||||||
def get_display_name(self):
|
def get_display_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@ -374,14 +374,21 @@ class Membership(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
self.club.name
|
f"{self.club.name} - {self.user.username} "
|
||||||
+ " - "
|
f"- {settings.SITH_CLUB_ROLES[self.role]} "
|
||||||
+ self.user.username
|
f"- {str(_('past member')) if self.end_date is not None else ''}"
|
||||||
+ " - "
|
|
||||||
+ str(settings.SITH_CLUB_ROLES[self.role])
|
|
||||||
+ str(" - " + str(_("past member")) if self.end_date is not None else "")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
if self.end_date is None:
|
||||||
|
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
|
||||||
|
else:
|
||||||
|
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("club:club_members", kwargs={"club_id": self.club_id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be super edited by the given user
|
Method to see if that object can be super edited by the given user
|
||||||
@ -401,16 +408,6 @@ class Membership(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("club:club_members", kwargs={"club_id": self.club_id})
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
if self.end_date is None:
|
|
||||||
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
|
|
||||||
else:
|
|
||||||
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
cache.delete(f"membership_{self.club_id}_{self.user_id}")
|
cache.delete(f"membership_{self.club_id}_{self.user_id}")
|
||||||
@ -452,6 +449,26 @@ class Mailing(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s - %s" % (self.club, self.email_full)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.is_moderated:
|
||||||
|
for user in (
|
||||||
|
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
|
.first()
|
||||||
|
.users.all()
|
||||||
|
):
|
||||||
|
if not user.notifications.filter(
|
||||||
|
type="MAILING_MODERATION", viewed=False
|
||||||
|
).exists():
|
||||||
|
Notification(
|
||||||
|
user=user,
|
||||||
|
url=reverse("com:mailing_admin"),
|
||||||
|
type="MAILING_MODERATION",
|
||||||
|
).save(*args, **kwargs)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if Mailing.objects.filter(email=self.email).exists():
|
if Mailing.objects.filter(email=self.email).exists():
|
||||||
raise ValidationError(_("This mailing list already exists."))
|
raise ValidationError(_("This mailing list already exists."))
|
||||||
@ -459,7 +476,7 @@ class Mailing(models.Model):
|
|||||||
self.is_moderated = True
|
self.is_moderated = True
|
||||||
else:
|
else:
|
||||||
self.moderator = None
|
self.moderator = None
|
||||||
super(Mailing, self).clean()
|
super().clean()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def email_full(self):
|
def email_full(self):
|
||||||
@ -481,7 +498,7 @@ class Mailing(models.Model):
|
|||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
self.subscriptions.all().delete()
|
self.subscriptions.all().delete()
|
||||||
super(Mailing, self).delete()
|
super().delete()
|
||||||
|
|
||||||
def fetch_format(self):
|
def fetch_format(self):
|
||||||
resp = self.email + ": "
|
resp = self.email + ": "
|
||||||
@ -489,26 +506,6 @@ class Mailing(models.Model):
|
|||||||
resp += sub.fetch_format()
|
resp += sub.fetch_format()
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def save(self):
|
|
||||||
if not self.is_moderated:
|
|
||||||
for user in (
|
|
||||||
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
|
||||||
.first()
|
|
||||||
.users.all()
|
|
||||||
):
|
|
||||||
if not user.notifications.filter(
|
|
||||||
type="MAILING_MODERATION", viewed=False
|
|
||||||
).exists():
|
|
||||||
Notification(
|
|
||||||
user=user,
|
|
||||||
url=reverse("com:mailing_admin"),
|
|
||||||
type="MAILING_MODERATION",
|
|
||||||
).save()
|
|
||||||
super(Mailing, self).save()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s" % (self.club, self.email_full)
|
|
||||||
|
|
||||||
|
|
||||||
class MailingSubscription(models.Model):
|
class MailingSubscription(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -536,6 +533,9 @@ class MailingSubscription(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (("user", "email", "mailing"),)
|
unique_together = (("user", "email", "mailing"),)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if not self.user and not self.email:
|
if not self.user and not self.email:
|
||||||
raise ValidationError(_("At least user or email is required"))
|
raise ValidationError(_("At least user or email is required"))
|
||||||
@ -550,7 +550,7 @@ class MailingSubscription(models.Model):
|
|||||||
)
|
)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
pass
|
pass
|
||||||
super(MailingSubscription, self).clean()
|
super().clean()
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
@ -578,6 +578,3 @@ class MailingSubscription(models.Model):
|
|||||||
|
|
||||||
def fetch_format(self):
|
def fetch_format(self):
|
||||||
return self.get_email + " "
|
return self.get_email + " "
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
@ -195,7 +194,7 @@ class ClubView(ClubTabsMixin, DetailView):
|
|||||||
current_tab = "infos"
|
current_tab = "infos"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ClubView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
if self.object.page and self.object.page.revisions.exists():
|
if self.object.page and self.object.page.revisions.exists():
|
||||||
kwargs["page_revision"] = self.object.page.revisions.last().content
|
kwargs["page_revision"] = self.object.page.revisions.last().content
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -209,10 +208,10 @@ class ClubRevView(ClubView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
self.revision = get_object_or_404(PageRev, pk=kwargs["rev_id"], page__club=obj)
|
self.revision = get_object_or_404(PageRev, pk=kwargs["rev_id"], page__club=obj)
|
||||||
return super(ClubRevView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ClubRevView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["page_revision"] = self.revision.content
|
kwargs["page_revision"] = self.revision.content
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -225,7 +224,7 @@ class ClubPageEditView(ClubTabsMixin, PageEditViewBase):
|
|||||||
self.club = get_object_or_404(Club, pk=kwargs["club_id"])
|
self.club = get_object_or_404(Club, pk=kwargs["club_id"])
|
||||||
if not self.club.page:
|
if not self.club.page:
|
||||||
raise Http404
|
raise Http404
|
||||||
return super(ClubPageEditView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
self.page = self.club.page
|
self.page = self.club.page
|
||||||
@ -269,14 +268,14 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
|
|||||||
current_tab = "members"
|
current_tab = "members"
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(ClubMembersView, self).get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["request_user"] = self.request.user
|
kwargs["request_user"] = self.request.user
|
||||||
kwargs["club"] = self.get_object()
|
kwargs["club"] = self.get_object()
|
||||||
kwargs["club_members"] = self.members
|
kwargs["club_members"] = self.members
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
kwargs = super(ClubMembersView, self).get_context_data(*args, **kwargs)
|
kwargs = super().get_context_data(*args, **kwargs)
|
||||||
kwargs["members"] = self.members
|
kwargs["members"] = self.members
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -284,7 +283,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
|
|||||||
"""
|
"""
|
||||||
Check user rights
|
Check user rights
|
||||||
"""
|
"""
|
||||||
resp = super(ClubMembersView, self).form_valid(form)
|
resp = super().form_valid(form)
|
||||||
|
|
||||||
data = form.clean()
|
data = form.clean()
|
||||||
users = data.pop("users", [])
|
users = data.pop("users", [])
|
||||||
@ -299,7 +298,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.members = self.get_object().members.ongoing().order_by("-role")
|
self.members = self.get_object().members.ongoing().order_by("-role")
|
||||||
return super(ClubMembersView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_success_url(self, **kwargs):
|
def get_success_url(self, **kwargs):
|
||||||
return reverse_lazy(
|
return reverse_lazy(
|
||||||
@ -333,12 +332,12 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.asked_page = int(request.GET.get("page", 1))
|
self.asked_page = int(request.GET.get("page", 1))
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise Http404
|
raise Http404 from e
|
||||||
return super(ClubSellingView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(ClubSellingView, self).get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["club"] = self.object
|
kwargs["club"] = self.object
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -346,7 +345,7 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
return self.get(request, *args, **kwargs)
|
return self.get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ClubSellingView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
qs = Selling.objects.filter(club=self.object)
|
qs = Selling.objects.filter(club=self.object)
|
||||||
|
|
||||||
kwargs["result"] = qs[:0]
|
kwargs["result"] = qs[:0]
|
||||||
@ -390,8 +389,8 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by)
|
kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by)
|
||||||
try:
|
try:
|
||||||
kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page)
|
kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page)
|
||||||
except InvalidPage:
|
except InvalidPage as e:
|
||||||
raise Http404
|
raise Http404 from e
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -558,7 +557,7 @@ class ClubStatView(TemplateView):
|
|||||||
template_name = "club/stats.jinja"
|
template_name = "club/stats.jinja"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ClubStatView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["club_list"] = Club.objects.all()
|
kwargs["club_list"] = Club.objects.all()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -575,7 +574,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
current_tab = "mailing"
|
current_tab = "mailing"
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(ClubMailingView, self).get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["club_id"] = self.get_object().id
|
kwargs["club_id"] = self.get_object().id
|
||||||
kwargs["user_id"] = self.request.user.id
|
kwargs["user_id"] = self.request.user.id
|
||||||
kwargs["mailings"] = self.mailings
|
kwargs["mailings"] = self.mailings
|
||||||
@ -583,10 +582,10 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.mailings = Mailing.objects.filter(club_id=self.get_object().id).all()
|
self.mailings = Mailing.objects.filter(club_id=self.get_object().id).all()
|
||||||
return super(ClubMailingView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ClubMailingView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["club"] = self.get_object()
|
kwargs["club"] = self.get_object()
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["mailings"] = self.mailings
|
kwargs["mailings"] = self.mailings
|
||||||
@ -670,7 +669,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
|||||||
sub.delete()
|
sub.delete()
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
resp = super(ClubMailingView, self).form_valid(form)
|
resp = super().form_valid(form)
|
||||||
|
|
||||||
cleaned_data = form.clean()
|
cleaned_data = form.clean()
|
||||||
error = None
|
error = None
|
||||||
@ -702,7 +701,7 @@ class MailingDeleteView(CanEditMixin, DeleteView):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.club_id = self.get_object().club.id
|
self.club_id = self.get_object().club.id
|
||||||
return super(MailingDeleteView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_success_url(self, **kwargs):
|
def get_success_url(self, **kwargs):
|
||||||
if self.redirect_page:
|
if self.redirect_page:
|
||||||
@ -718,9 +717,7 @@ class MailingSubscriptionDeleteView(CanEditMixin, DeleteView):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.club_id = self.get_object().mailing.club.id
|
self.club_id = self.get_object().mailing.club.id
|
||||||
return super(MailingSubscriptionDeleteView, self).dispatch(
|
return super().dispatch(request, *args, **kwargs)
|
||||||
request, *args, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_success_url(self, **kwargs):
|
def get_success_url(self, **kwargs):
|
||||||
return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id})
|
return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id})
|
||||||
@ -731,7 +728,7 @@ class MailingAutoGenerationView(View):
|
|||||||
self.mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"])
|
self.mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"])
|
||||||
if not request.user.can_edit(self.mailing):
|
if not request.user.can_edit(self.mailing):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return super(MailingAutoGenerationView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
club = self.mailing.club
|
club = self.mailing.club
|
||||||
@ -751,7 +748,7 @@ class PosterListView(ClubTabsMixin, PosterListBaseView, CanViewMixin):
|
|||||||
return self.club
|
return self.club
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterListView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "club"
|
kwargs["app"] = "club"
|
||||||
kwargs["club"] = self.club
|
kwargs["club"] = self.club
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -763,7 +760,7 @@ class PosterCreateView(PosterCreateBaseView, CanCreateMixin):
|
|||||||
pk_url_kwarg = "club_id"
|
pk_url_kwarg = "club_id"
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
obj = super(PosterCreateView, self).get_object()
|
obj = super().get_object()
|
||||||
if not obj:
|
if not obj:
|
||||||
return self.club
|
return self.club
|
||||||
return obj
|
return obj
|
||||||
@ -779,7 +776,7 @@ class PosterEditView(ClubTabsMixin, PosterEditBaseView, CanEditMixin):
|
|||||||
return reverse_lazy("club:poster_list", kwargs={"club_id": self.club.id})
|
return reverse_lazy("club:poster_list", kwargs={"club_id": self.club.id})
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterEditView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "club"
|
kwargs["app"] = "club"
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.23 on 2019-08-18 17:00
|
# Generated by Django 1.11.23 on 2019-08-18 17:00
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
@ -47,14 +46,14 @@ class Sith(models.Model):
|
|||||||
weekmail_destinations = models.TextField(_("weekmail destinations"), default="")
|
weekmail_destinations = models.TextField(_("weekmail destinations"), default="")
|
||||||
version = utils.get_git_revision_short_hash()
|
version = utils.get_git_revision_short_hash()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "⛩ Sith ⛩"
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "⛩ Sith ⛩"
|
|
||||||
|
|
||||||
|
|
||||||
NEWS_TYPES = [
|
NEWS_TYPES = [
|
||||||
("NOTICE", _("Notice")),
|
("NOTICE", _("Notice")),
|
||||||
@ -91,28 +90,11 @@ class News(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
if user.is_anonymous:
|
|
||||||
return False
|
|
||||||
return user.is_com_admin or user == self.author
|
|
||||||
|
|
||||||
def can_be_edited_by(self, user):
|
|
||||||
return user.is_com_admin
|
|
||||||
|
|
||||||
def can_be_viewed_by(self, user):
|
|
||||||
return self.is_moderated or user.is_com_admin
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("com:news_detail", kwargs={"news_id": self.id})
|
|
||||||
|
|
||||||
def get_full_url(self):
|
|
||||||
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s: %s" % (self.type, self.title)
|
return "%s: %s" % (self.type, self.title)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super(News, self).save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
for u in (
|
for u in (
|
||||||
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
.first()
|
.first()
|
||||||
@ -125,6 +107,23 @@ class News(models.Model):
|
|||||||
param="1",
|
param="1",
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("com:news_detail", kwargs={"news_id": self.id})
|
||||||
|
|
||||||
|
def get_full_url(self):
|
||||||
|
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
if user.is_anonymous:
|
||||||
|
return False
|
||||||
|
return user.is_com_admin or user == self.author
|
||||||
|
|
||||||
|
def can_be_edited_by(self, user):
|
||||||
|
return user.is_com_admin
|
||||||
|
|
||||||
|
def can_be_viewed_by(self, user):
|
||||||
|
return self.is_moderated or user.is_com_admin
|
||||||
|
|
||||||
|
|
||||||
def news_notification_callback(notif):
|
def news_notification_callback(notif):
|
||||||
count = (
|
count = (
|
||||||
@ -186,6 +185,9 @@ class Weekmail(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-id"]
|
ordering = ["-id"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Weekmail {self.id} (sent: {self.sent}) - {self.title}"
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
"""
|
"""
|
||||||
Send the weekmail to all users with the receive weekmail option opt-in.
|
Send the weekmail to all users with the receive weekmail option opt-in.
|
||||||
@ -241,9 +243,6 @@ class Weekmail(models.Model):
|
|||||||
"""
|
"""
|
||||||
return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png")
|
return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png")
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "Weekmail %s (sent: %s) - %s" % (self.id, self.sent, self.title)
|
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
@ -274,18 +273,21 @@ class WeekmailArticle(models.Model):
|
|||||||
)
|
)
|
||||||
rank = models.IntegerField(_("rank"), default=-1)
|
rank = models.IntegerField(_("rank"), default=-1)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
|
||||||
|
|
||||||
|
|
||||||
class Screen(models.Model):
|
class Screen(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=128)
|
name = models.CharField(_("name"), max_length=128)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def active_posters(self):
|
def active_posters(self):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
|
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
|
||||||
@ -297,9 +299,6 @@ class Screen(models.Model):
|
|||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s" % (self.name)
|
|
||||||
|
|
||||||
|
|
||||||
class Poster(models.Model):
|
class Poster(models.Model):
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
@ -329,6 +328,9 @@ class Poster(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.is_moderated:
|
if not self.is_moderated:
|
||||||
for u in (
|
for u in (
|
||||||
@ -341,7 +343,7 @@ class Poster(models.Model):
|
|||||||
url=reverse("com:poster_moderate_list"),
|
url=reverse("com:poster_moderate_list"),
|
||||||
type="POSTER_MODERATION",
|
type="POSTER_MODERATION",
|
||||||
).save()
|
).save()
|
||||||
return super(Poster, self).save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self, *args, **kwargs):
|
def clean(self, *args, **kwargs):
|
||||||
if self.date_end and self.date_begin > self.date_end:
|
if self.date_end and self.date_begin > self.date_end:
|
||||||
@ -361,6 +363,3 @@ class Poster(models.Model):
|
|||||||
@property
|
@property
|
||||||
def page(self):
|
def page(self):
|
||||||
return self.club.page
|
return self.club.page
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
114
com/views.py
114
com/views.py
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
@ -82,7 +81,7 @@ class PosterForm(forms.ModelForm):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.user = kwargs.pop("user", None)
|
self.user = kwargs.pop("user", None)
|
||||||
super(PosterForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
if self.user:
|
if self.user:
|
||||||
if not self.user.is_com_admin:
|
if not self.user.is_com_admin:
|
||||||
self.fields["club"].queryset = Club.objects.filter(
|
self.fields["club"].queryset = Club.objects.filter(
|
||||||
@ -145,7 +144,7 @@ class IsComAdminMixin(View):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not request.user.is_com_admin:
|
if not request.user.is_com_admin:
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
|
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
|
||||||
@ -199,7 +198,7 @@ class NewsForm(forms.ModelForm):
|
|||||||
automoderation = forms.BooleanField(label=_("Automoderation"), required=False)
|
automoderation = forms.BooleanField(label=_("Automoderation"), required=False)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.cleaned_data = super(NewsForm, self).clean()
|
self.cleaned_data = super().clean()
|
||||||
if self.cleaned_data["type"] != "NOTICE":
|
if self.cleaned_data["type"] != "NOTICE":
|
||||||
if not self.cleaned_data["start_date"]:
|
if not self.cleaned_data["start_date"]:
|
||||||
self.add_error(
|
self.add_error(
|
||||||
@ -225,7 +224,7 @@ class NewsForm(forms.ModelForm):
|
|||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
ret = super(NewsForm, self).save()
|
ret = super().save()
|
||||||
self.instance.dates.all().delete()
|
self.instance.dates.all().delete()
|
||||||
if self.instance.type == "EVENT" or self.instance.type == "CALL":
|
if self.instance.type == "EVENT" or self.instance.type == "CALL":
|
||||||
NewsDate(
|
NewsDate(
|
||||||
@ -252,24 +251,10 @@ class NewsEditView(CanEditMixin, UpdateView):
|
|||||||
pk_url_kwarg = "news_id"
|
pk_url_kwarg = "news_id"
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
init = {}
|
news_date: NewsDate = self.object.dates.order_by("id").first()
|
||||||
try:
|
if news_date is None:
|
||||||
init["start_date"] = (
|
return {"start_date": None, "end_date": None}
|
||||||
self.object.dates.order_by("id")
|
return {"start_date": news_date.start_date, "end_date": news_date.end_date}
|
||||||
.first()
|
|
||||||
.start_date.strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
init["end_date"] = (
|
|
||||||
self.object.dates.order_by("id")
|
|
||||||
.first()
|
|
||||||
.end_date.strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return init
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
@ -302,7 +287,7 @@ class NewsEditView(CanEditMixin, UpdateView):
|
|||||||
),
|
),
|
||||||
type="NEWS_MODERATION",
|
type="NEWS_MODERATION",
|
||||||
).save()
|
).save()
|
||||||
return super(NewsEditView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class NewsCreateView(CanCreateMixin, CreateView):
|
class NewsCreateView(CanCreateMixin, CreateView):
|
||||||
@ -312,10 +297,9 @@ class NewsCreateView(CanCreateMixin, CreateView):
|
|||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
init = {"author": self.request.user}
|
init = {"author": self.request.user}
|
||||||
try:
|
if "club" not in self.request.GET:
|
||||||
|
return init
|
||||||
init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
|
init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return init
|
return init
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
@ -346,7 +330,7 @@ class NewsCreateView(CanCreateMixin, CreateView):
|
|||||||
url=reverse("com:news_admin_list"),
|
url=reverse("com:news_admin_list"),
|
||||||
type="NEWS_MODERATION",
|
type="NEWS_MODERATION",
|
||||||
).save()
|
).save()
|
||||||
return super(NewsCreateView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class NewsDeleteView(CanEditMixin, DeleteView):
|
class NewsDeleteView(CanEditMixin, DeleteView):
|
||||||
@ -385,7 +369,7 @@ class NewsListView(CanViewMixin, ListView):
|
|||||||
queryset = News.objects.filter(is_moderated=True)
|
queryset = News.objects.filter(is_moderated=True)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(NewsListView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["NewsDate"] = NewsDate
|
kwargs["NewsDate"] = NewsDate
|
||||||
kwargs["timedelta"] = timedelta
|
kwargs["timedelta"] = timedelta
|
||||||
kwargs["birthdays"] = (
|
kwargs["birthdays"] = (
|
||||||
@ -416,7 +400,7 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.bad_recipients = []
|
self.bad_recipients = []
|
||||||
return super(WeekmailPreviewView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
@ -437,14 +421,14 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai
|
|||||||
u.preferences.receive_weekmail = False
|
u.preferences.receive_weekmail = False
|
||||||
u.preferences.save()
|
u.preferences.save()
|
||||||
self.quick_notif_list += ["qn_success"]
|
self.quick_notif_list += ["qn_success"]
|
||||||
return super(WeekmailPreviewView, self).get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
return self.model.objects.filter(sent=False).order_by("-id").first()
|
return self.model.objects.filter(sent=False).order_by("-id").first()
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add rendered weekmail"""
|
"""Add rendered weekmail"""
|
||||||
kwargs = super(WeekmailPreviewView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["weekmail_rendered"] = self.object.render_html()
|
kwargs["weekmail_rendered"] = self.object.render_html()
|
||||||
kwargs["bad_recipients"] = self.bad_recipients
|
kwargs["bad_recipients"] = self.bad_recipients
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -520,11 +504,11 @@ class WeekmailEditView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateVi
|
|||||||
art.rank = -1
|
art.rank = -1
|
||||||
art.save()
|
art.save()
|
||||||
self.quick_notif_list += ["qn_success"]
|
self.quick_notif_list += ["qn_success"]
|
||||||
return super(WeekmailEditView, self).get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add orphan articles"""
|
"""Add orphan articles"""
|
||||||
kwargs = super(WeekmailEditView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None)
|
kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None)
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -561,22 +545,16 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
|
|||||||
quick_notif_url_arg = "qn_weekmail_new_article"
|
quick_notif_url_arg = "qn_weekmail_new_article"
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
init = {}
|
if "club" not in self.request.GET:
|
||||||
try:
|
return {}
|
||||||
init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
|
return {"club": Club.objects.filter(id=self.request.GET.get("club")).first()}
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return init
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
self.object = form.instance
|
self.object = form.instance
|
||||||
form.is_valid() # Valid a first time to populate club field
|
form.is_valid() # Valid a first time to populate club field
|
||||||
try:
|
|
||||||
m = form.instance.club.get_membership_for(request.user)
|
m = form.instance.club.get_membership_for(request.user)
|
||||||
if m.role <= settings.SITH_MAXIMUM_FREE_ROLE:
|
if m is None or m.role <= settings.SITH_MAXIMUM_FREE_ROLE:
|
||||||
raise
|
|
||||||
except:
|
|
||||||
form.add_error(
|
form.add_error(
|
||||||
"club",
|
"club",
|
||||||
ValidationError(
|
ValidationError(
|
||||||
@ -592,7 +570,7 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
|
|||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.instance.author = self.request.user
|
form.instance.author = self.request.user
|
||||||
return super(WeekmailArticleCreateView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView):
|
class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView):
|
||||||
@ -612,10 +590,10 @@ class MailingListAdminView(ComTabsMixin, ListView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not (request.user.is_com_admin or request.user.is_root):
|
if not (request.user.is_com_admin or request.user.is_root):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return super(MailingListAdminView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(MailingListAdminView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all()
|
kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all()
|
||||||
kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all()
|
kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all()
|
||||||
kwargs["has_moderated"] = len(kwargs["moderated"]) > 0
|
kwargs["has_moderated"] = len(kwargs["moderated"]) > 0
|
||||||
@ -647,7 +625,7 @@ class PosterListBaseView(ListView):
|
|||||||
self.club = None
|
self.club = None
|
||||||
if club_id:
|
if club_id:
|
||||||
self.club = get_object_or_404(Club, pk=club_id)
|
self.club = get_object_or_404(Club, pk=club_id)
|
||||||
return super(PosterListBaseView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if self.request.user.is_com_admin:
|
if self.request.user.is_com_admin:
|
||||||
@ -656,7 +634,7 @@ class PosterListBaseView(ListView):
|
|||||||
return Poster.objects.filter(club=self.club.id)
|
return Poster.objects.filter(club=self.club.id)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterListBaseView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
if not self.request.user.is_com_admin:
|
if not self.request.user.is_com_admin:
|
||||||
kwargs["club"] = self.club
|
kwargs["club"] = self.club
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -675,15 +653,15 @@ class PosterCreateBaseView(CreateView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if "club_id" in kwargs:
|
if "club_id" in kwargs:
|
||||||
self.club = get_object_or_404(Club, pk=kwargs["club_id"])
|
self.club = get_object_or_404(Club, pk=kwargs["club_id"])
|
||||||
return super(PosterCreateBaseView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(PosterCreateBaseView, self).get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs.update({"user": self.request.user})
|
kwargs.update({"user": self.request.user})
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterCreateBaseView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
if not self.request.user.is_com_admin:
|
if not self.request.user.is_com_admin:
|
||||||
kwargs["club"] = self.club
|
kwargs["club"] = self.club
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -691,7 +669,7 @@ class PosterCreateBaseView(CreateView):
|
|||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
if self.request.user.is_com_admin:
|
if self.request.user.is_com_admin:
|
||||||
form.instance.is_moderated = True
|
form.instance.is_moderated = True
|
||||||
return super(PosterCreateBaseView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class PosterEditBaseView(UpdateView):
|
class PosterEditBaseView(UpdateView):
|
||||||
@ -718,20 +696,20 @@ class PosterEditBaseView(UpdateView):
|
|||||||
if "club_id" in kwargs and kwargs["club_id"]:
|
if "club_id" in kwargs and kwargs["club_id"]:
|
||||||
try:
|
try:
|
||||||
self.club = Club.objects.get(pk=kwargs["club_id"])
|
self.club = Club.objects.get(pk=kwargs["club_id"])
|
||||||
except Club.DoesNotExist:
|
except Club.DoesNotExist as e:
|
||||||
raise PermissionDenied
|
raise PermissionDenied from e
|
||||||
return super(PosterEditBaseView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Poster.objects.all()
|
return Poster.objects.all()
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(PosterEditBaseView, self).get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs.update({"user": self.request.user})
|
kwargs.update({"user": self.request.user})
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterEditBaseView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
if hasattr(self, "club"):
|
if hasattr(self, "club"):
|
||||||
kwargs["club"] = self.club
|
kwargs["club"] = self.club
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -739,7 +717,7 @@ class PosterEditBaseView(UpdateView):
|
|||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
if self.request.user.is_com_admin:
|
if self.request.user.is_com_admin:
|
||||||
form.instance.is_moderated = False
|
form.instance.is_moderated = False
|
||||||
return super(PosterEditBaseView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class PosterDeleteBaseView(DeleteView):
|
class PosterDeleteBaseView(DeleteView):
|
||||||
@ -754,16 +732,16 @@ class PosterDeleteBaseView(DeleteView):
|
|||||||
if "club_id" in kwargs and kwargs["club_id"]:
|
if "club_id" in kwargs and kwargs["club_id"]:
|
||||||
try:
|
try:
|
||||||
self.club = Club.objects.get(pk=kwargs["club_id"])
|
self.club = Club.objects.get(pk=kwargs["club_id"])
|
||||||
except Club.DoesNotExist:
|
except Club.DoesNotExist as e:
|
||||||
raise PermissionDenied
|
raise PermissionDenied from e
|
||||||
return super(PosterDeleteBaseView, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView):
|
class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView):
|
||||||
"""List communication posters"""
|
"""List communication posters"""
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterListView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "com"
|
kwargs["app"] = "com"
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -774,7 +752,7 @@ class PosterCreateView(IsComAdminMixin, ComTabsMixin, PosterCreateBaseView):
|
|||||||
success_url = reverse_lazy("com:poster_list")
|
success_url = reverse_lazy("com:poster_list")
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterCreateView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "com"
|
kwargs["app"] = "com"
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -785,7 +763,7 @@ class PosterEditView(IsComAdminMixin, ComTabsMixin, PosterEditBaseView):
|
|||||||
success_url = reverse_lazy("com:poster_list")
|
success_url = reverse_lazy("com:poster_list")
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterEditView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "com"
|
kwargs["app"] = "com"
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -805,7 +783,7 @@ class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView):
|
|||||||
queryset = Poster.objects.filter(is_moderated=False).all()
|
queryset = Poster.objects.filter(is_moderated=False).all()
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["app"] = "com"
|
kwargs["app"] = "com"
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -844,7 +822,7 @@ class ScreenSlideshowView(DetailView):
|
|||||||
template_name = "com/screen_slideshow.jinja"
|
template_name = "com/screen_slideshow.jinja"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["posters"] = self.object.active_posters()
|
kwargs["posters"] = self.object.active_posters()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2017
|
# Copyright 2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
@ -24,11 +24,11 @@ class Command(BaseCommand):
|
|||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
deps = settings.SITH_FRONT_DEP_VERSIONS
|
deps = settings.SITH_FRONT_DEP_VERSIONS
|
||||||
|
|
||||||
processes = dict(
|
processes = {
|
||||||
(url, create_process(url))
|
url: create_process(url)
|
||||||
for url in deps.keys()
|
for url in deps.keys()
|
||||||
if parse_semver(deps[url]) is not None
|
if parse_semver(deps[url]) is not None
|
||||||
)
|
}
|
||||||
|
|
||||||
for url, process in processes.items():
|
for url, process in processes.items():
|
||||||
try:
|
try:
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2018
|
# Copyright 2018
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2019
|
# Copyright 2019
|
||||||
# - Sli <antoine@bartuccio.fr>
|
# - Sli <antoine@bartuccio.fr>
|
||||||
@ -41,4 +40,4 @@ class Command(compilemessages.Command):
|
|||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
os.chdir("sith")
|
os.chdir("sith")
|
||||||
super(Command, self).handle(*args, **options)
|
super().handle(*args, **options)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2017
|
# Copyright 2017
|
||||||
# - Sli <antoine@bartuccio.fr>
|
# - Sli <antoine@bartuccio.fr>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2019
|
# Copyright 2019
|
||||||
# - Sli <antoine@bartuccio.fr>
|
# - Sli <antoine@bartuccio.fr>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2024 © AE UTBM
|
# Copyright 2024 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -47,7 +46,7 @@ class Command(BaseCommand):
|
|||||||
pyproject = tomli.load(f)
|
pyproject = tomli.load(f)
|
||||||
return pyproject["tool"]["xapian"]["version"]
|
return pyproject["tool"]["xapian"]["version"]
|
||||||
|
|
||||||
def handle(self, force: bool, *args, **options):
|
def handle(self, *args, force: bool, **options):
|
||||||
if not os.environ.get("VIRTUAL_ENV", None):
|
if not os.environ.get("VIRTUAL_ENV", None):
|
||||||
print("No virtual environment detected, this command can't be used")
|
print("No virtual environment detected, this command can't be used")
|
||||||
return
|
return
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Originates from https://gist.github.com/jorgecarleitao/ab6246c86c936b9c55fd
|
# Originates from https://gist.github.com/jorgecarleitao/ab6246c86c936b9c55fd
|
||||||
# first argument of the script is Xapian version (e.g. 1.2.19)
|
# first argument of the script is Xapian version (e.g. 1.2.19)
|
||||||
VERSION=$1
|
VERSION="$1"
|
||||||
|
|
||||||
# Cleanup env vars for auto discovery mechanism
|
# Cleanup env vars for auto discovery mechanism
|
||||||
export CPATH=
|
export CPATH=
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2017
|
# Copyright 2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2016,2017,2023
|
# Copyright 2016,2017,2023
|
||||||
# - Skia <skia@hya.sk>
|
# - Skia <skia@hya.sk>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2018
|
# Copyright 2018
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
|
241
core/markdown.py
241
core/markdown.py
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -13,163 +12,125 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import mistune
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from mistune import InlineGrammar, InlineLexer, Markdown, Renderer, escape, escape_link
|
from mistune import HTMLRenderer, Markdown
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from mistune import InlineParser, InlineState
|
||||||
|
|
||||||
|
# match __text__, without linebreak in the text, nor backslash prepending an underscore
|
||||||
|
# Examples :
|
||||||
|
# - "__text__" : OK
|
||||||
|
# - "__te xt__" : OK
|
||||||
|
# - "__te_xt__" : nope (underscore in the middle)
|
||||||
|
# - "__te\_xt__" : Ok (the middle underscore is escaped)
|
||||||
|
# - "__te\nxt__" : nope (there is a linebreak in the text)
|
||||||
|
# - "\__text__" : nope (one of the underscores have a backslash prepended)
|
||||||
|
# - "\\__text__" : Ok (the backslash is ignored, because there is another backslash before)
|
||||||
|
UNDERLINED_RE = (
|
||||||
|
r"(?<!\\)(?:\\{2})*" # ignore if there is an odd number of backslashes before
|
||||||
|
r"_{2}" # two underscores
|
||||||
|
r"(?P<underlined>([^\\_]|\\.)+)" # the actual text
|
||||||
|
r"_{2}" # closing underscores
|
||||||
|
)
|
||||||
|
|
||||||
|
SITH_LINK_RE = (
|
||||||
|
r"\[(?P<page_name>[\w\s]+)\]" # [nom du lien]
|
||||||
|
r"\(page:\/\/" # (page://
|
||||||
|
r"(?P<page_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
||||||
|
r"\)" # )
|
||||||
|
)
|
||||||
|
|
||||||
|
CUSTOM_DIMENSIONS_IMAGE_RE = (
|
||||||
|
r"\[(?P<img_name>[\w\s]+)\]" # [nom du lien]
|
||||||
|
r"\(img:\/\/" # (img://
|
||||||
|
r"(?P<img_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
||||||
|
r"\)" # )
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SithRenderer(Renderer):
|
def parse_underline(_inline: InlineParser, m: re.Match, state: InlineState):
|
||||||
def file_link(self, id, suffix):
|
state.append_token({"type": "underline", "raw": m.group("underlined")})
|
||||||
return reverse("core:file_detail", kwargs={"file_id": id}) + suffix
|
return m.end()
|
||||||
|
|
||||||
def exposant(self, text):
|
|
||||||
return """<sup>%s</sup>""" % text
|
|
||||||
|
|
||||||
def indice(self, text):
|
def underline(md_instance: Markdown):
|
||||||
return """<sub>%s</sub>""" % text
|
md_instance.inline.register(
|
||||||
|
"underline",
|
||||||
|
UNDERLINED_RE,
|
||||||
|
parse_underline,
|
||||||
|
before="emphasis",
|
||||||
|
)
|
||||||
|
md_instance.renderer.register("underline", lambda _, text: f"<u>{text}</u>")
|
||||||
|
|
||||||
def underline(self, text):
|
|
||||||
return """<u>%s</u>""" % text
|
|
||||||
|
|
||||||
def image(self, original_src, title, text):
|
def parse_sith_link(_inline: InlineParser, m: re.Match, state: InlineState):
|
||||||
"""Rendering a image with title and text.
|
page_name = m.group("page_name")
|
||||||
:param src: source link of the image.
|
page_slug = m.group("page_slug")
|
||||||
:param title: title text of the image.
|
state.append_token(
|
||||||
:param text: alt text of the image.
|
{
|
||||||
"""
|
"type": "link",
|
||||||
style = None
|
"children": [{"type": "text", "raw": page_name}],
|
||||||
if "?" in original_src:
|
"attrs": {"url": reverse("core:page", kwargs={"page_name": page_slug})},
|
||||||
src, params = original_src.rsplit("?", maxsplit=1)
|
}
|
||||||
m = re.search(r"(\d+%?)(x(\d+%?))?", params)
|
)
|
||||||
|
return m.end()
|
||||||
|
|
||||||
|
|
||||||
|
def sith_link(md_instance: Markdown):
|
||||||
|
md_instance.inline.register(
|
||||||
|
"sith_link",
|
||||||
|
SITH_LINK_RE,
|
||||||
|
parse_sith_link,
|
||||||
|
before="emphasis",
|
||||||
|
)
|
||||||
|
# no custom renderer here.
|
||||||
|
# we just add another parsing rule, but render it as if it was
|
||||||
|
# a regular markdown link
|
||||||
|
|
||||||
|
|
||||||
|
class SithRenderer(HTMLRenderer):
|
||||||
|
def image(self, text: str, url: str, title=None) -> str:
|
||||||
|
if "?" not in url:
|
||||||
|
return super().image(text, url, title)
|
||||||
|
|
||||||
|
new_url, params = url.rsplit("?", maxsplit=1)
|
||||||
|
m = re.match(r"^(?P<width>\d+(%|px)?)(x(?P<height>\d+(%|px)?))?$", params)
|
||||||
if not m:
|
if not m:
|
||||||
src = original_src
|
return super().image(text, url, title)
|
||||||
else:
|
|
||||||
width = m.group(1)
|
width, height = m.group("width"), m.group("height")
|
||||||
if not width.endswith("%"):
|
if not width.endswith(("%", "px")):
|
||||||
width += "px"
|
width += "px"
|
||||||
style = "width: %s; " % width
|
style = f"width:{width};"
|
||||||
try:
|
if height is not None:
|
||||||
height = m.group(3)
|
if not height.endswith(("%", "px")):
|
||||||
if not height.endswith("%"):
|
|
||||||
height += "px"
|
height += "px"
|
||||||
style += "height: %s; " % height
|
style += f"height:{height};"
|
||||||
except:
|
return super().image(text, new_url, title).replace("/>", f'style="{style}" />')
|
||||||
pass
|
|
||||||
else:
|
|
||||||
params = None
|
|
||||||
src = original_src
|
|
||||||
src = escape_link(src)
|
|
||||||
text = escape(text, quote=True)
|
|
||||||
if title:
|
|
||||||
title = escape(title, quote=True)
|
|
||||||
html = '<img src="%s" alt="%s" title="%s"' % (src, text, title)
|
|
||||||
else:
|
|
||||||
html = '<img src="%s" alt="%s"' % (src, text)
|
|
||||||
if style:
|
|
||||||
html = '%s style="%s"' % (html, style)
|
|
||||||
if self.options.get("use_xhtml"):
|
|
||||||
return "%s />" % html
|
|
||||||
return "%s>" % html
|
|
||||||
|
|
||||||
|
|
||||||
class SithInlineGrammar(InlineGrammar):
|
markdown = mistune.create_markdown(
|
||||||
double_emphasis = re.compile(r"^\*{2}([\s\S]+?)\*{2}(?!\*)") # **word**
|
renderer=SithRenderer(escape=True),
|
||||||
emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)\*(?!\*)") # *word*
|
plugins=[
|
||||||
underline = re.compile(r"^_{2}([\s\S]+?)_{2}(?!_)") # __word__
|
underline,
|
||||||
exposant = re.compile(r"^<sup>([\s\S]+?)</sup>") # <sup>text</sup>
|
sith_link,
|
||||||
indice = re.compile(r"^<sub>([\s\S]+?)</sub>") # <sub>text</sub>
|
|
||||||
|
|
||||||
|
|
||||||
class SithInlineLexer(InlineLexer):
|
|
||||||
grammar_class = SithInlineGrammar
|
|
||||||
|
|
||||||
default_rules = [
|
|
||||||
"escape",
|
|
||||||
# 'inline_html',
|
|
||||||
"autolink",
|
|
||||||
"url",
|
|
||||||
"footnote",
|
|
||||||
"link",
|
|
||||||
"reflink",
|
|
||||||
"nolink",
|
|
||||||
"exposant",
|
|
||||||
"double_emphasis",
|
|
||||||
"emphasis",
|
|
||||||
"underline",
|
|
||||||
"indice",
|
|
||||||
"code",
|
|
||||||
"linebreak",
|
|
||||||
"strikethrough",
|
"strikethrough",
|
||||||
"text",
|
"footnotes",
|
||||||
]
|
"table",
|
||||||
inline_html_rules = [
|
"spoiler",
|
||||||
"escape",
|
"subscript",
|
||||||
"autolink",
|
"superscript",
|
||||||
"url",
|
"url",
|
||||||
"link",
|
],
|
||||||
"reflink",
|
)
|
||||||
"nolink",
|
|
||||||
"exposant",
|
|
||||||
"double_emphasis",
|
|
||||||
"emphasis",
|
|
||||||
"underline",
|
|
||||||
"indice",
|
|
||||||
"code",
|
|
||||||
"linebreak",
|
|
||||||
"strikethrough",
|
|
||||||
"text",
|
|
||||||
]
|
|
||||||
|
|
||||||
def output_underline(self, m):
|
|
||||||
text = m.group(1)
|
|
||||||
return self.renderer.underline(text)
|
|
||||||
|
|
||||||
def output_exposant(self, m):
|
|
||||||
text = m.group(1)
|
|
||||||
return self.renderer.exposant(text)
|
|
||||||
|
|
||||||
def output_indice(self, m):
|
|
||||||
text = m.group(1)
|
|
||||||
return self.renderer.indice(text)
|
|
||||||
|
|
||||||
# Double emphasis rule changed
|
|
||||||
def output_double_emphasis(self, m):
|
|
||||||
text = m.group(1)
|
|
||||||
text = self.output(text)
|
|
||||||
return self.renderer.double_emphasis(text)
|
|
||||||
|
|
||||||
# Emphasis rule changed
|
|
||||||
def output_emphasis(self, m):
|
|
||||||
text = m.group(1)
|
|
||||||
text = self.output(text)
|
|
||||||
return self.renderer.emphasis(text)
|
|
||||||
|
|
||||||
def _process_link(self, m, link, title=None):
|
|
||||||
try: # Add page:// support for links
|
|
||||||
page = re.compile(r"^page://(\S*)") # page://nom_de_ma_page
|
|
||||||
match = page.search(link)
|
|
||||||
page = match.group(1) or ""
|
|
||||||
link = reverse("core:page", kwargs={"page_name": page})
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try: # Add file:// support for links
|
|
||||||
file_link = re.compile(r"^file://(\d*)/?(\S*)?") # file://4000/download
|
|
||||||
match = file_link.search(link)
|
|
||||||
id = match.group(1)
|
|
||||||
suffix = match.group(2) or ""
|
|
||||||
link = reverse("core:file_detail", kwargs={"file_id": id}) + suffix
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return super(SithInlineLexer, self)._process_link(m, link, title)
|
|
||||||
|
|
||||||
|
|
||||||
renderer = SithRenderer(escape=True)
|
|
||||||
inline = SithInlineLexer(renderer)
|
|
||||||
|
|
||||||
markdown = Markdown(renderer, inline=inline)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding:utf-8 -*
|
|
||||||
#
|
#
|
||||||
# Copyright 2023 © AE UTBM
|
# Copyright 2023 © AE UTBM
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
# ae@utbm.fr / ae.info@utbm.fr
|
||||||
@ -69,5 +68,5 @@ class SignalRequestMiddleware:
|
|||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
setattr(_threadlocal, "request", request)
|
_threadlocal.request = request
|
||||||
return self.get_response(request)
|
return self.get_response(request)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
@ -574,7 +573,7 @@ class Migration(migrations.Migration):
|
|||||||
managers=[("objects", core.models.RealGroupManager())],
|
managers=[("objects", core.models.RealGroupManager())],
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="page", unique_together=set([("name", "parent")])
|
name="page", unique_together={("name", "parent")}
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="user",
|
model_name="user",
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user