diff --git a/club/forms.py b/club/forms.py index 80d4c058..57ab91da 100644 --- a/club/forms.py +++ b/club/forms.py @@ -31,20 +31,10 @@ from django.forms.models import ModelChoiceField, ModelChoiceIterator from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ -from club.models import ( - Club, - ClubLink, - ClubRole, - Mailing, - MailingSubscription, - Membership, -) +from club.models import Club, ClubLink, ClubRole, Membership from core.models import User from core.views.forms import SelectDateTime -from core.views.widgets.ajax_select import ( - AutoCompleteSelectMultipleUser, - AutoCompleteSelectUser, -) +from core.views.widgets.ajax_select import AutoCompleteSelectUser from counter.models import Counter, Selling from counter.schemas import SaleFilterSchema @@ -131,107 +121,6 @@ class ClubAdminEditForm(ClubEditForm): fields = ["name", "parent", "is_active", *ClubEditForm.Meta.fields] -class MailingForm(forms.Form): - """Form handling mailing lists right.""" - - ACTION_NEW_MAILING = 1 - ACTION_NEW_SUBSCRIPTION = 2 - ACTION_REMOVE_SUBSCRIPTION = 3 - - subscription_users = forms.ModelMultipleChoiceField( - label=_("Users to add"), - help_text=_("Search users to add (one or more)."), - required=False, - widget=AutoCompleteSelectMultipleUser, - queryset=User.objects.all(), - ) - - def __init__(self, club_id, user_id, mailings, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.fields["action"] = forms.TypedChoiceField( - choices=( - (self.ACTION_NEW_MAILING, _("New Mailing")), - (self.ACTION_NEW_SUBSCRIPTION, _("Subscribe")), - (self.ACTION_REMOVE_SUBSCRIPTION, _("Remove")), - ), - coerce=int, - label=_("Action"), - initial=1, - required=True, - widget=forms.HiddenInput(), - ) - - # Generate bulk removal forms, they are never required - for mailing in mailings: - self.fields["removal_" + str(mailing.id)] = forms.ModelMultipleChoiceField( - mailing.subscriptions.all(), - label=_("Remove"), - required=False, - widget=forms.CheckboxSelectMultiple, - ) - - # Include fields for handling mailing creation - mailing_fields = ("email",) - self.fields.update(forms.fields_for_model(Mailing, fields=mailing_fields)) - for field in mailing_fields: - self.fields["mailing_" + field] = self.fields.pop(field) - self.fields["mailing_" + field].required = False - - # Include fields for handling subscription creation - subscription_fields = ("mailing", "email") - self.fields.update( - forms.fields_for_model(MailingSubscription, fields=subscription_fields) - ) - for field in subscription_fields: - self.fields["subscription_" + field] = self.fields.pop(field) - self.fields["subscription_" + field].required = False - - self.fields["subscription_mailing"].queryset = Mailing.objects.filter( - club__id=club_id, is_moderated=True - ) - - def check_required(self, cleaned_data, field): - """If the given field doesn't exist or has no value, add a required error on it.""" - if not cleaned_data.get(field, None): - self.add_error(field, _("This field is required")) - - def clean_subscription_users(self): - """Convert given users into real users and check their validity.""" - cleaned_data = super().clean() - users = [] - for user in cleaned_data["subscription_users"]: - if not user.email: - raise forms.ValidationError( - _("One of the selected users doesn't have an email address"), - code="invalid", - ) - users.append(user) - return users - - def clean(self): - cleaned_data = super().clean() - - if "action" not in cleaned_data: - # If there is no action provided, we can stop here - raise forms.ValidationError(_("An action is required"), code="invalid") - - if cleaned_data["action"] == self.ACTION_NEW_MAILING: - self.check_required(cleaned_data, "mailing_email") - - if cleaned_data["action"] == self.ACTION_NEW_SUBSCRIPTION: - self.check_required(cleaned_data, "subscription_mailing") - if not cleaned_data.get( - "subscription_users", None - ) and not cleaned_data.get("subscription_email", None): - raise forms.ValidationError( - _("You must specify at least an user or an email address"), - code="invalid", - ) - - return cleaned_data - - class SellingsForm(forms.Form): begin_date = forms.DateTimeField( label=_("Begin date"), widget=SelectDateTime, required=False diff --git a/club/migrations/0019_remove_mailingsubscription_mailing_and_more.py b/club/migrations/0019_remove_mailingsubscription_mailing_and_more.py new file mode 100644 index 00000000..de4046c6 --- /dev/null +++ b/club/migrations/0019_remove_mailingsubscription_mailing_and_more.py @@ -0,0 +1,16 @@ +# Generated by Django 5.2.17 on 2026-10-15 13:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [("club", "0018_clubrole_linked_groups")] + + operations = [ + migrations.AlterUniqueTogether( + name="mailingsubscription", unique_together=None + ), + migrations.RemoveField(model_name="mailingsubscription", name="user"), + migrations.DeleteModel(name="Mailing"), + migrations.DeleteModel(name="MailingSubscription"), + ] diff --git a/club/models.py b/club/models.py index 6c2baec8..90648804 100644 --- a/club/models.py +++ b/club/models.py @@ -28,8 +28,7 @@ from functools import reduce from typing import Iterable, Self from django.conf import settings -from django.core.exceptions import ObjectDoesNotExist, ValidationError -from django.core.validators import RegexValidator, validate_email +from django.core.exceptions import ValidationError from django.db import ProgrammingError, models, transaction from django.db.models import Exists, F, OuterRef, Q from django.urls import reverse @@ -41,7 +40,7 @@ from django.utils.translation import gettext_lazy as _ from ordered_model.models import OrderedModel from core.fields import ResizedImageField -from core.models import Group, Notification, Page, SithFile, User +from core.models import Group, Page, SithFile, User class ClubQuerySet(models.QuerySet): @@ -633,169 +632,6 @@ class Membership(models.Model): return User.groups.through.objects.bulk_create(groups, ignore_conflicts=True) -class Mailing(models.Model): - """A Mailing list for a club. - - Warning: - Remember that mailing lists should be validated by UTBM. - """ - - club = models.ForeignKey( - Club, - verbose_name=_("Club"), - related_name="mailings", - null=False, - blank=False, - on_delete=models.CASCADE, - ) - email = models.CharField( - _("Email address"), - unique=True, - null=False, - blank=False, - max_length=256, - validators=[ - RegexValidator( - validate_email.user_regex, - _("Enter a valid address. Only the root of the address is needed."), - ) - ], - ) - is_moderated = models.BooleanField(_("is moderated"), default=False) - moderator = models.ForeignKey( - User, - related_name="moderated_mailings", - verbose_name=_("moderator"), - null=True, - 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: - unread_notif_subquery = Notification.objects.filter( - user=OuterRef("pk"), type="MAILING_MODERATION", viewed=False - ) - for user in User.objects.filter( - ~Exists(unread_notif_subquery), - groups__id__in=[settings.SITH_GROUP_COM_ADMIN_ID], - ): - Notification( - user=user, - url=reverse("com:mailing_admin"), - type="MAILING_MODERATION", - ).save(*args, **kwargs) - super().save(*args, **kwargs) - - def clean(self): - if Mailing.objects.filter(email=self.email).exists(): - raise ValidationError(_("This mailing list already exists.")) - if self.can_moderate(self.moderator): - self.is_moderated = True - else: - self.moderator = None - super().clean() - - @property - def email_full(self): - return self.email + "@" + settings.SITH_MAILING_DOMAIN - - def can_moderate(self, user): - return user.is_root or user.is_com_admin - - def is_owned_by(self, user): - if user.is_anonymous: - return False - return user.is_root or user.is_com_admin - - def can_view(self, user): - return self.club.has_rights_in_club(user) - - def can_be_edited_by(self, user): - return self.club.has_rights_in_club(user) - - def delete(self, *args, **kwargs): - self.subscriptions.all().delete() - super().delete() - - def fetch_format(self): - destination = "".join(s.fetch_format() for s in self.subscriptions.all()) - return f"{self.email}: {destination}" - - -class MailingSubscription(models.Model): - """Link between user and mailing list.""" - - mailing = models.ForeignKey( - Mailing, - verbose_name=_("Mailing"), - related_name="subscriptions", - null=False, - blank=False, - on_delete=models.CASCADE, - ) - user = models.ForeignKey( - User, - verbose_name=_("User"), - related_name="mailing_subscriptions", - null=True, - blank=True, - on_delete=models.CASCADE, - ) - email = models.EmailField(_("Email address"), blank=False, null=False) - - class Meta: - unique_together = (("user", "email", "mailing"),) - - def __str__(self): - return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email) - - def clean(self): - if not self.user and not self.email: - raise ValidationError(_("At least user or email is required")) - try: - if self.user and not self.email: - self.email = self.user.email - if MailingSubscription.objects.filter( - mailing=self.mailing, email=self.email - ).exists(): - raise ValidationError( - _("This email is already suscribed in this mailing") - ) - except ObjectDoesNotExist: - pass - super().clean() - - def is_owned_by(self, user): - if user.is_anonymous: - return False - return ( - self.mailing.club.has_rights_in_club(user) - or user.is_root - or self.user.is_com_admin - ) - - def can_be_edited_by(self, user): - return self.user is not None and user.id == self.user.id - - @cached_property - def get_email(self): - if self.user and not self.email: - return self.user.email - return self.email - - @cached_property - def get_username(self): - if self.user: - return str(self.user) - return _("Unregistered user") - - def fetch_format(self): - return self.get_email + " " - - class LinkType(models.Model): """A link type, in order to group links and give them icons. diff --git a/club/templates/club/club_tools.jinja b/club/templates/club/club_tools.jinja index a69d5c26..3c4e2e6e 100644 --- a/club/templates/club/club_tools.jinja +++ b/club/templates/club/club_tools.jinja @@ -15,9 +15,6 @@ {% trans %}Post in the Weekmail{% endtrans %} - {% if object.can_roles_be_edited_by(user) %} -
  • - {% endif %} {% if object.trombi %}
  • {% trans %}Edit Trombi{% endtrans %}
  • {% else %} diff --git a/club/templates/club/mailing.jinja b/club/templates/club/mailing.jinja deleted file mode 100644 index a7421602..00000000 --- a/club/templates/club/mailing.jinja +++ /dev/null @@ -1,108 +0,0 @@ -{% extends "core/base.jinja" %} -{% from 'core/macros.jinja' import select_all_checkbox %} - -{% block title %} - {% trans %}Mailing lists{% endtrans %} -{% endblock %} - -{% block content %} - - {% trans %}Remember : mailing lists need to be moderated, if your new created list is not shown wait until moderation takes action{% endtrans %} - - {% if mailings_not_moderated %} -

    {% trans %}Mailing lists waiting for moderation{% endtrans %}

    - - {% endif %} - - {% if mailings_moderated %} - {% for mailing in mailings_moderated %} -

    {% trans %}Mailing{% endtrans %} {{ mailing.email_full }} - {%- if user.is_owner(mailing) -%} - - {% trans %}Delete{% endtrans %} - {%- endif -%} -

    -
    - -
    - {% set form_mailing_removal = form["removal_" + mailing.id|string] %} - {% if form_mailing_removal.field.choices %} - {% set ms = dict(mailing.subscriptions.all() | groupby('id')) %} -
    -

    {{ select_all_checkbox(form_mailing_removal.auto_id) }}

    - {% csrf_token %} - - - - - - - - - - - {% for widget in form_mailing_removal.subwidgets %} - {% set user = ms[widget.data.value.value][0] %} - - - - - - {% endfor %} - -
    {% trans %}User{% endtrans %}{% trans %}Email{% endtrans %}{% trans %}Delete{% endtrans %}
    {{ user.get_username }}{{ user.get_email }}{{ widget.tag() }}
    - {{ form_mailing_removal.errors }} -

    -
    - - {% else %} -

    {% trans %}There is no subscriber for this mailing list{% endtrans %}

    - {% endif %} - {% endfor %} - - {% else %} -

    {% trans %}No mailing list existing for this club{% endtrans %}

    - {% endif %} - -

    {{ form.non_field_errors() }}

    - {% if mailings_moderated %} -

    {% trans %}New member{% endtrans %}

    -
    - {% csrf_token %} -

    - {{ form.subscription_mailing.errors }} - - {{ form.subscription_mailing }} -

    -

    - {{ form.subscription_users.errors }} - - {{ form.subscription_users }} - {{ form.subscription_users.help_text }} -

    -

    - {{ form.subscription_email.errors }} - - {{ form.subscription_email }} -

    - -

    -
    - {% endif %} - -

    {% trans %}New mailing{% endtrans %}

    -
    - {% csrf_token %} -

    - {{ form.mailing_email.errors }} - - {{ form.mailing_email }} -

    - -

    -
    - -{% endblock %} diff --git a/club/tests/test_mailing.py b/club/tests/test_mailing.py deleted file mode 100644 index 2217281c..00000000 --- a/club/tests/test_mailing.py +++ /dev/null @@ -1,328 +0,0 @@ -from django.conf import settings -from django.test import TestCase -from django.urls import reverse -from django.utils import timezone -from django.utils.translation import gettext as _ -from model_bakery import baker - -from club.forms import MailingForm -from club.models import Club, ClubRole, Mailing, Membership -from core.models import User - - -class TestMailingForm(TestCase): - """Perform validation tests for MailingForm.""" - - @classmethod - def setUpTestData(cls): - cls.skia = User.objects.get(username="skia") - cls.rbatsbak = User.objects.get(username="rbatsbak") - cls.krophil = User.objects.get(username="krophil") - cls.comunity = User.objects.get(username="comunity") - cls.root = User.objects.get(username="root") - cls.club = Club.objects.get(id=settings.SITH_PDF_CLUB_ID) - cls.mail_url = reverse("club:mailing", kwargs={"club_id": cls.club.id}) - Membership( - user=cls.rbatsbak, - club=cls.club, - start_date=timezone.now(), - role=baker.make(ClubRole, club=cls.club, is_board=True), - ).save() - - def test_mailing_list_add_no_moderation(self): - # Test with Communication admin - self.client.force_login(self.comunity) - response = self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "foyer"}, - ) - self.assertRedirects(response, self.mail_url) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - assert "Liste de diffusion foyer@utbm.fr" in response.text - - # Test with Root - self.client.force_login(self.root) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - assert "Liste de diffusion mde@utbm.fr" in response.text - - def test_mailing_list_add_moderation(self): - self.client.force_login(self.rbatsbak) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - assert "Liste de diffusion mde@utbm.fr" not in content - assert "

    Listes de diffusions en attente de modération

    " in content - assert "
  • mde@utbm.fr" in content - - def test_mailing_list_forbidden(self): - # With anonymous user - response = self.client.get(self.mail_url) - self.assertContains(response, "", status_code=403) - - # With user not in club - self.client.force_login(self.krophil) - response = self.client.get(self.mail_url) - assert response.status_code == 403 - - def test_add_new_subscription_fail_not_moderated(self): - self.client.force_login(self.rbatsbak) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.skia.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - assert "skia@git.an" not in response.text - - def test_add_new_subscription_success(self): - # Prepare mailing list - self.client.force_login(self.comunity) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - - # Add single user - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.skia.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - assert "skia@git.an" in response.text - - # Add multiple users - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": (self.comunity.id, self.rbatsbak.id), - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - assert "richard@git.an" in content - assert "comunity@git.an" in content - assert "skia@git.an" in content - - # Add arbitrary email - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_email": "arbitrary@git.an", - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - assert "richard@git.an" in content - assert "comunity@git.an" in content - assert "skia@git.an" in content - assert "arbitrary@git.an" in content - - # Add user and arbitrary email - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_email": "more.arbitrary@git.an", - "subscription_users": self.krophil.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - assert "richard@git.an" in content - assert "comunity@git.an" in content - assert "skia@git.an" in content - assert "arbitrary@git.an" in content - assert "more.arbitrary@git.an" in content - assert "krophil@git.an" in content - - def test_add_new_subscription_fail_form_errors(self): - # Prepare mailing list - self.client.force_login(self.comunity) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - - # Neither email or email is specified - response = self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - assert response.status_code - self.assertInHTML( - _("You must specify at least an user or an email address"), - response.text, - ) - - # No mailing specified - response = self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.krophil.id, - }, - ) - assert response.status_code == 200 - assert _("This field is required") in response.text - - # One of the selected users doesn't exist - response = self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": [789], - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - assert response.status_code == 200 - self.assertInHTML( - _("You must specify at least an user or an email address"), - response.text, - ) - - # An user has no email address - self.krophil.email = "" - self.krophil.save() - - response = self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.krophil.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - assert response.status_code == 200 - self.assertInHTML( - _("One of the selected users doesn't have an email address"), - response.text, - ) - - self.krophil.email = "krophil@git.an" - self.krophil.save() - - # An user is added twice - - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.krophil.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - - response = self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": self.krophil.id, - "subscription_mailing": Mailing.objects.get(email="mde").id, - }, - ) - assert response.status_code == 200 - self.assertInHTML( - _("This email is already suscribed in this mailing"), - response.text, - ) - - def test_remove_subscription_success(self): - # Prepare mailing list - self.client.force_login(self.comunity) - self.client.post( - self.mail_url, - {"action": MailingForm.ACTION_NEW_MAILING, "mailing_email": "mde"}, - ) - mde = Mailing.objects.get(email="mde") - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_NEW_SUBSCRIPTION, - "subscription_users": ( - self.comunity.id, - self.rbatsbak.id, - self.krophil.id, - ), - "subscription_mailing": mde.id, - }, - ) - - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - - assert "comunity@git.an" in content - assert "richard@git.an" in content - assert "krophil@git.an" in content - - # Delete one user - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_REMOVE_SUBSCRIPTION, - "removal_%d" % mde.id: mde.subscriptions.get(user=self.krophil).id, - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - - assert "comunity@git.an" in content - assert "richard@git.an" in content - assert "krophil@git.an" not in content - - # Delete multiple users - self.client.post( - self.mail_url, - { - "action": MailingForm.ACTION_REMOVE_SUBSCRIPTION, - "removal_%d" % mde.id: [ - user.id - for user in mde.subscriptions.filter( - user__in=[self.rbatsbak, self.comunity] - ).all() - ], - }, - ) - response = self.client.get(self.mail_url) - assert response.status_code == 200 - content = response.text - - assert "comunity@git.an" not in content - assert "richard@git.an" not in content - assert "krophil@git.an" not in content diff --git a/club/urls.py b/club/urls.py index 6a08bbe5..3195b1ae 100644 --- a/club/urls.py +++ b/club/urls.py @@ -29,7 +29,6 @@ from club.views import ( ClubCreateView, ClubEditView, ClubListView, - ClubMailingView, ClubMembersView, ClubOldMembersView, ClubPageEditView, @@ -43,9 +42,6 @@ from club.views import ( ClubSellingView, ClubToolsView, ClubView, - MailingAutoGenerationView, - MailingDeleteView, - MailingSubscriptionDeleteView, MembershipDeleteView, MembershipSetOldView, PosterCreateView, @@ -96,22 +92,6 @@ urlpatterns = [ "/sellings/csv/", ClubSellingCSVView.as_view(), name="sellings_csv" ), path("/tools/", ClubToolsView.as_view(), name="tools"), - path("/mailing/", ClubMailingView.as_view(), name="mailing"), - path( - "/mailing/generate/", - MailingAutoGenerationView.as_view(), - name="mailing_generate", - ), - path( - "/mailing/delete/", - MailingDeleteView.as_view(), - name="mailing_delete", - ), - path( - "/mailing/delete/subscription/", - MailingSubscriptionDeleteView.as_view(), - name="mailing_subscription_delete", - ), path( "membership//set_old/", MembershipSetOldView.as_view(), diff --git a/club/views.py b/club/views.py index 6f2c7716..c9f4f28e 100644 --- a/club/views.py +++ b/club/views.py @@ -34,7 +34,6 @@ from django.contrib.auth.mixins import ( UserPassesTestMixin, ) from django.contrib.messages.views import SuccessMessageMixin -from django.core.exceptions import NON_FIELD_ERRORS, PermissionDenied, ValidationError from django.core.paginator import InvalidPage, Paginator from django.db.models import F, Prefetch, Q, Sum from django.db.models.functions import Length @@ -59,7 +58,6 @@ from club.forms import ( ClubRoleFormSet, ClubSearchForm, JoinClubForm, - MailingForm, SellingsForm, ) from club.models import ( @@ -67,8 +65,6 @@ from club.models import ( ClubLink, ClubRole, LinkType, - Mailing, - MailingSubscription, Membership, ) from com.models import Poster @@ -181,13 +177,6 @@ class ClubTabsMixin(TabedViewMixin): "slug": "sellings", "name": _("Sellings"), }, - { - "url": reverse( - "club:mailing", kwargs={"club_id": self.object.id} - ), - "slug": "mailing", - "name": _("Mailing list"), - }, { "url": reverse( "club:poster_list", kwargs={"club_id": self.object.id} @@ -742,166 +731,6 @@ class MembershipDeleteView(PermissionRequiredMixin, DeleteView): return reverse_lazy("core:user_clubs", kwargs={"user_id": self.object.user_id}) -class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView): - """A list of mailing for a given club.""" - - model = Club - form_class = MailingForm - pk_url_kwarg = "club_id" - template_name = "club/mailing.jinja" - current_tab = "mailing" - - def get_form_kwargs(self): - kwargs = super().get_form_kwargs() - kwargs["club_id"] = self.object.id - kwargs["user_id"] = self.request.user.id - kwargs["mailings"] = self.object.mailings.all() - return kwargs - - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - mailings = list(self.object.mailings.all()) - kwargs["club"] = self.object - kwargs["user"] = self.request.user - kwargs["mailings"] = mailings - kwargs["mailings_moderated"] = [m for m in mailings if m.is_moderated] - kwargs["mailings_not_moderated"] = [m for m in mailings if not m.is_moderated] - kwargs["form_actions"] = { - "NEW_MALING": self.form_class.ACTION_NEW_MAILING, - "NEW_SUBSCRIPTION": self.form_class.ACTION_NEW_SUBSCRIPTION, - "REMOVE_SUBSCRIPTION": self.form_class.ACTION_REMOVE_SUBSCRIPTION, - } - return kwargs - - def add_new_mailing(self, cleaned_data) -> ValidationError | None: - """Create a new mailing list from the form.""" - mailing = Mailing( - club=self.object, - email=cleaned_data["mailing_email"], - moderator=self.request.user, - is_moderated=False, - ) - try: - mailing.clean() - except ValidationError as validation_error: - return validation_error - mailing.save() - return None - - def add_new_subscription(self, cleaned_data) -> ValidationError | None: - """Add mailing subscriptions for each user given and/or for the specified email in form.""" - users_to_save = [] - - for user in cleaned_data["subscription_users"]: - sub = MailingSubscription( - mailing=cleaned_data["subscription_mailing"], user=user - ) - try: - sub.clean() - except ValidationError as validation_error: - return validation_error - - sub.save() - users_to_save.append(sub) - - if cleaned_data["subscription_email"]: - sub = MailingSubscription( - mailing=cleaned_data["subscription_mailing"], - email=cleaned_data["subscription_email"], - ) - - try: - sub.clean() - except ValidationError as validation_error: - return validation_error - sub.save() - - # Save users after we are sure there is no error - for user in users_to_save: - user.save() - - return None - - def remove_subscription(self, cleaned_data): - """Remove specified users from a mailing list.""" - fields = [ - val for key, val in cleaned_data.items() if key.startswith("removal_") - ] - for field in fields: - for sub in field: - sub.delete() - - def form_valid(self, form): - resp = super().form_valid(form) - - cleaned_data = form.clean() - error = None - - if cleaned_data["action"] == self.form_class.ACTION_NEW_MAILING: - error = self.add_new_mailing(cleaned_data) - - if cleaned_data["action"] == self.form_class.ACTION_NEW_SUBSCRIPTION: - error = self.add_new_subscription(cleaned_data) - - if cleaned_data["action"] == self.form_class.ACTION_REMOVE_SUBSCRIPTION: - self.remove_subscription(cleaned_data) - - if error: - form.add_error(NON_FIELD_ERRORS, error) - return self.form_invalid(form) - - return resp - - def get_success_url(self, **kwargs): - return reverse("club:mailing", kwargs={"club_id": self.object.id}) - - -class MailingDeleteView(CanEditMixin, DeleteView): - model = Mailing - template_name = "core/delete_confirm.jinja" - pk_url_kwarg = "mailing_id" - redirect_page = None - - def dispatch(self, request, *args, **kwargs): - self.club_id = self.get_object().club.id - return super().dispatch(request, *args, **kwargs) - - def get_success_url(self, **kwargs): - if self.redirect_page: - return reverse_lazy(self.redirect_page) - else: - return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id}) - - -class MailingSubscriptionDeleteView(CanEditMixin, DeleteView): - model = MailingSubscription - template_name = "core/delete_confirm.jinja" - pk_url_kwarg = "mailing_subscription_id" - - def dispatch(self, request, *args, **kwargs): - self.club_id = self.get_object().mailing.club.id - return super().dispatch(request, *args, **kwargs) - - def get_success_url(self, **kwargs): - return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id}) - - -class MailingAutoGenerationView(View): - def dispatch(self, request, *args, **kwargs): - self.mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"]) - if not request.user.can_edit(self.mailing): - raise PermissionDenied - return super().dispatch(request, *args, **kwargs) - - def get(self, request, *args, **kwargs): - club = self.mailing.club - self.mailing.subscriptions.all().delete() - members = club.members.ongoing().filter(role__is_board=True) - for member in members.all(): - MailingSubscription(user=member.user, mailing=self.mailing).save() - return redirect("club:mailing", club_id=club.id) - - class PosterListView( PermissionOrClubBoardRequiredMixin, ClubTabsMixin, PosterListBaseView ): diff --git a/com/models.py b/com/models.py index 6a9100b5..3f3e332a 100644 --- a/com/models.py +++ b/com/models.py @@ -259,10 +259,7 @@ class Weekmail(models.Model): return f"Weekmail {self.id} (sent: {self.sent}) - {self.title}" def send(self): - """Send the weekmail to all users with the receive weekmail option opt-in. - - Also send the weekmail to the mailing list in settings.SITH_COM_EMAIL. - """ + """Send the weekmail to all users with the receive weekmail option opt-in.""" dest = [ i[0] for i in Preferences.objects.filter(receive_weekmail=True).values_list( diff --git a/com/templates/com/mailing_admin.jinja b/com/templates/com/mailing_admin.jinja deleted file mode 100644 index 3096e435..00000000 --- a/com/templates/com/mailing_admin.jinja +++ /dev/null @@ -1,45 +0,0 @@ -{% extends "core/base.jinja" %} - -{% block title %} - {% trans %}Mailing lists administration{% endtrans %} -{% endblock %} - -{% macro display_mailings(list) %} - - - - - - - {% for mailing in list %} - - - - - - {% endfor %} -
    {% trans %}Email{% endtrans %}{% trans %}Club{%endtrans%}{% trans %}Actions{% endtrans %}
    {{ mailing.email_full }}{{ mailing.club }} - {% trans %}Delete{% endtrans %} - {% if not mailing.is_moderated %}{% trans %}Moderate{% endtrans %}{% else %}{% trans user=mailing.moderator %}Moderated by {{ user }}{% endtrans %}{% endif %} -
    - -{% endmacro %} - -{% block content %} -

    {% trans %}This page lists all mailing lists{% endtrans %}

    - - {% if has_unmoderated %} -

    {% trans %}Not moderated mailing lists{% endtrans %}

    - {{ display_mailings(unmoderated) }} - {% endif %} - -

    {% trans %}Moderated mailing lists{% endtrans %}

    - {% if has_moderated %} - {{ display_mailings(moderated) }} - {% else %} -

    {% trans %}No mailing list existing{% endtrans %}

    - {% endif %} - -{% endblock %} - - - diff --git a/com/urls.py b/com/urls.py index 51861316..d94b0f50 100644 --- a/com/urls.py +++ b/com/urls.py @@ -15,12 +15,9 @@ from django.urls import path -from club.views import MailingDeleteView from com.views import ( AlertMsgEditView, InfoMsgEditView, - MailingListAdminView, - MailingModerateView, NewsAdminListView, NewsCreateView, NewsDeleteView, @@ -82,17 +79,6 @@ urlpatterns = [ "news//moderate/", NewsModerateView.as_view(), name="news_moderate" ), path("news//", NewsDetailView.as_view(), name="news_detail"), - path("mailings/", MailingListAdminView.as_view(), name="mailing_admin"), - path( - "mailings//moderate/", - MailingModerateView.as_view(), - name="mailing_moderate", - ), - path( - "mailings//delete/", - MailingDeleteView.as_view(redirect_page="com:mailing_admin"), - name="mailing_delete", - ), path("poster/", PosterListView.as_view(), name="poster_list"), path("poster/create/", PosterCreateView.as_view(), name="poster_create"), path("poster//edit/", PosterEditView.as_view(), name="poster_edit"), diff --git a/com/views.py b/com/views.py index 82075aa8..9f845370 100644 --- a/com/views.py +++ b/com/views.py @@ -30,11 +30,9 @@ from urllib.parse import urlparse from dateutil.relativedelta import relativedelta from django.conf import settings from django.contrib import messages -from django.contrib.auth.mixins import ( - PermissionRequiredMixin, -) +from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.syndication.views import Feed -from django.core.exceptions import PermissionDenied, ValidationError +from django.core.exceptions import ValidationError from django.db.models import Exists, Max, OuterRef, Value from django.forms.models import modelform_factory from django.http import HttpResponseRedirect @@ -46,7 +44,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, ListView, TemplateView, View from django.views.generic.edit import CreateView, DeleteView, UpdateView -from club.models import Club, Mailing, Membership +from club.models import Club, Membership from com.forms import NewsDateForm, NewsForm, PosterForm from com.ics_calendar import IcsCalendar from com.models import News, NewsDate, Poster, Screen, Sith, Weekmail, WeekmailArticle @@ -86,11 +84,6 @@ class ComTabsMixin(TabedViewMixin): "slug": "alert", "name": _("Alert message"), }, - { - "url": reverse("com:mailing_admin"), - "slug": "mailings", - "name": _("Mailing lists administration"), - }, { "url": reverse("com:poster_list"), "slug": "posters", @@ -533,37 +526,6 @@ class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView): pk_url_kwarg = "article_id" -class MailingListAdminView(ComTabsMixin, ListView): - template_name = "com/mailing_admin.jinja" - model = Mailing - current_tab = "mailings" - - def dispatch(self, request, *args, **kwargs): - if not (request.user.is_com_admin or request.user.is_root): - raise PermissionDenied - return super().dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all() - kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all() - kwargs["has_moderated"] = len(kwargs["moderated"]) > 0 - kwargs["has_unmoderated"] = len(kwargs["unmoderated"]) > 0 - return kwargs - - -class MailingModerateView(View): - def get(self, request, *args, **kwargs): - mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"]) - if mailing.can_moderate(request.user): - mailing.is_moderated = True - mailing.moderator = request.user - mailing.save() - return redirect("com:mailing_admin") - - raise PermissionDenied - - class PosterListBaseView(ListView): """List communication posters.""" diff --git a/core/api.py b/core/api.py index d46548f5..075ae5b1 100644 --- a/core/api.py +++ b/core/api.py @@ -1,18 +1,15 @@ from typing import Annotated, Literal from annotated_types import Ge, Le, MinLen -from django.conf import settings from django.db.models import F from ninja import File, Query from ninja.security import SessionAuth from ninja_extra import ControllerBase, api_controller, paginate, route -from ninja_extra.exceptions import PermissionDenied from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.schemas import PaginatedResponseSchema from api.auth import ApiKeyAuth from api.permissions import CanAccessLookup, CanView, HasPerm -from club.models import Mailing from core.models import Group, QuickUploadImage, SithFile, User from core.schemas import ( FamilyGodfatherSchema, @@ -48,19 +45,6 @@ class UploadController(ControllerBase): return image -@api_controller("/mailings") -class MailingListController(ControllerBase): - @route.get("", response=str) - def fetch_mailing_lists(self, key: str): - if key != settings.SITH_MAILING_FETCH_KEY: - raise PermissionDenied - mailings = Mailing.objects.filter( - is_moderated=True, club__is_active=True - ).prefetch_related("subscriptions") - data = "\n".join(m.fetch_format() for m in mailings) - return data - - @api_controller("/user") class UserController(ControllerBase): @route.get("", response=list[UserProfileSchema]) diff --git a/core/templates/core/user_clubs.jinja b/core/templates/core/user_clubs.jinja index afc6748e..bd352abe 100644 --- a/core/templates/core/user_clubs.jinja +++ b/core/templates/core/user_clubs.jinja @@ -79,15 +79,5 @@ {% endfor %} - - {% if - profile.mailing_subscriptions.exists() - and (profile.id == user.id or user.is_root or user.is_com_admin) - %} -

    {% trans %}Subscribed mailing lists{% endtrans %}

    - {% for sub in profile.mailing_subscriptions.all() %} -

    {{ sub.mailing.email }} {% trans %}Unsubscribe{% endtrans %}

    - {% endfor %} -{% endif %} {% endblock %} diff --git a/core/templates/core/user_tools.jinja b/core/templates/core/user_tools.jinja index a9fb76b6..9206eca3 100644 --- a/core/templates/core/user_tools.jinja +++ b/core/templates/core/user_tools.jinja @@ -133,7 +133,6 @@
  • {% trans %}Edit alert message{% endtrans %}
  • {% trans %}Edit information message{% endtrans %}
  • {% trans %}Moderate files{% endtrans %}
  • -
  • {% trans %}Mailing lists administration{% endtrans %}
  • {% trans %}Posters{% endtrans %}
  • {% trans %}Screens{% endtrans %}
  • {% endif %} diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index eadaed9e..a7095881 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-10-09 21:44+0200\n" +"POT-Creation-Date: 2026-10-15 15:20+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Maréchal \n" @@ -192,46 +192,6 @@ msgstr "" "arrivée durant l'interaction avec l'application tierce. Veuillez contacter " "les responsables de cette dernière." -#: club/forms.py -msgid "Users to add" -msgstr "Utilisateurs à ajouter" - -#: club/forms.py core/views/group.py -msgid "Search users to add (one or more)." -msgstr "Recherche les utilisateurs à ajouter (un ou plus)." - -#: club/forms.py -msgid "New Mailing" -msgstr "Nouvelle mailing liste" - -#: club/forms.py -msgid "Subscribe" -msgstr "S'abonner" - -#: club/forms.py -msgid "Remove" -msgstr "Retirer" - -#: club/forms.py counter/forms.py pedagogy/templates/pedagogy/moderation.jinja -msgid "Action" -msgstr "Action" - -#: club/forms.py club/tests/test_mailing.py -msgid "This field is required" -msgstr "Ce champ est obligatoire" - -#: club/forms.py club/tests/test_mailing.py -msgid "One of the selected users doesn't have an email address" -msgstr "Un des utilisateurs sélectionnés n'a pas d'adresse email" - -#: club/forms.py -msgid "An action is required" -msgstr "Une action est requise" - -#: club/forms.py club/tests/test_mailing.py -msgid "You must specify at least an user or an email address" -msgstr "vous devez spécifier au moins un utilisateur ou une adresse email" - #: club/forms.py counter/forms.py msgid "Begin date" msgstr "Date de début" @@ -414,60 +374,6 @@ msgstr "rôle" msgid "past member" msgstr "ancien membre" -#: club/models.py com/templates/com/mailing_admin.jinja -#: com/templates/com/news_admin_list.jinja com/templates/com/weekmail.jinja -#: core/templates/core/user_clubs.jinja -#: counter/templates/counter/invoices_call.jinja -#: trombi/templates/trombi/edit_profile.jinja -#: trombi/templates/trombi/export.jinja -#: trombi/templates/trombi/user_profile.jinja -msgid "Club" -msgstr "Club" - -#: club/models.py -msgid "Email address" -msgstr "Adresse email" - -#: club/models.py -msgid "Enter a valid address. Only the root of the address is needed." -msgstr "" -"Entrez une adresse valide. Seule la racine de l'adresse est nécessaire." - -#: club/models.py com/models.py core/models.py -msgid "is moderated" -msgstr "est modéré" - -#: club/models.py com/models.py -msgid "moderator" -msgstr "modérateur" - -#: club/models.py -msgid "This mailing list already exists." -msgstr "Cette liste de diffusion existe déjà." - -#: club/models.py club/templates/club/mailing.jinja -msgid "Mailing" -msgstr "Liste de diffusion" - -#: club/models.py club/templates/club/club_members.jinja -#: club/templates/club/club_old_members.jinja club/templates/club/mailing.jinja -#: counter/templates/counter/cash_summary_list.jinja -#: counter/templates/counter/stats.jinja -msgid "User" -msgstr "Utilisateur" - -#: club/models.py -msgid "At least user or email is required" -msgstr "Au moins un utilisateur ou un email est nécessaire" - -#: club/models.py club/tests/test_mailing.py -msgid "This email is already suscribed in this mailing" -msgstr "Cet email est déjà abonné à cette mailing" - -#: club/models.py -msgid "Unregistered user" -msgstr "Utilisateur non enregistré" - #: club/models.py msgid "The base url that links with this type must respect" msgstr "L'url de base que tous les liens de ce type doivent respecter" @@ -554,6 +460,13 @@ msgstr "Membres du club" msgid "Manage roles" msgstr "Gérer les rôles" +#: club/templates/club/club_members.jinja +#: club/templates/club/club_old_members.jinja +#: counter/templates/counter/cash_summary_list.jinja +#: counter/templates/counter/stats.jinja +msgid "User" +msgstr "Utilisateur" + #: club/templates/club/club_members.jinja #: club/templates/club/club_old_members.jinja #: core/templates/core/user_clubs.jinja @@ -817,8 +730,7 @@ msgstr "Total" msgid "Payment method" msgstr "Méthode de paiement" -#: club/templates/club/club_sellings.jinja club/templates/club/mailing.jinja -#: com/templates/com/macros.jinja com/templates/com/mailing_admin.jinja +#: club/templates/club/club_sellings.jinja com/templates/com/macros.jinja #: com/templates/com/news_admin_list.jinja com/templates/com/poster_edit.jinja #: com/templates/com/screen_edit.jinja com/templates/com/weekmail.jinja #: core/templates/core/file_detail.jinja @@ -944,60 +856,6 @@ msgstr "Ajouter" msgid "Join" msgstr "Rejoindre" -#: club/templates/club/mailing.jinja -msgid "Mailing lists" -msgstr "Mailing listes" - -#: club/templates/club/mailing.jinja -msgid "" -"Remember : mailing lists need to be moderated, if your new created list is " -"not shown wait until moderation takes action" -msgstr "" -"Rappelez vous : les mailing listes doivent être modérées, si votre liste " -"nouvellement créée n'est pas affichée, attendez jusqu'à ce qu'un modérateur " -"prenne une décision" - -#: club/templates/club/mailing.jinja -msgid "Mailing lists waiting for moderation" -msgstr "Listes de diffusions en attente de modération" - -#: club/templates/club/mailing.jinja -msgid "Generate mailing list" -msgstr "Générer la liste de diffusion" - -#: club/templates/club/mailing.jinja com/templates/com/mailing_admin.jinja -msgid "Email" -msgstr "Email" - -#: club/templates/club/mailing.jinja -msgid "Remove from mailing list" -msgstr "Supprimer de la liste de diffusion" - -#: club/templates/club/mailing.jinja -msgid "There is no subscriber for this mailing list" -msgstr "Il n'y a pas d'abonnés dans cette liste de diffusion" - -#: club/templates/club/mailing.jinja -msgid "No mailing list existing for this club" -msgstr "Aucune mailing liste n'existe pour ce club" - -#: club/templates/club/mailing.jinja -#: subscription/templates/subscription/subscription.jinja -msgid "New member" -msgstr "Nouveau membre" - -#: club/templates/club/mailing.jinja -msgid "Add to mailing list" -msgstr "Ajouter à la mailing liste" - -#: club/templates/club/mailing.jinja -msgid "New mailing" -msgstr "Nouvelle liste de diffusion" - -#: club/templates/club/mailing.jinja -msgid "Create mailing list" -msgstr "Créer une liste de diffusion" - #: club/templates/club/pagerev_edit.jinja core/templates/core/page/edit.jinja msgid "Edit page" msgstr "Éditer la page" @@ -1043,10 +901,6 @@ msgstr "Éditer la page de club" msgid "Sellings" msgstr "Vente" -#: club/views.py -msgid "Mailing list" -msgstr "Listes de diffusion" - #: club/views.py msgid "You are now a member of this club." msgstr "Vous êtes maintenant membre de ce club." @@ -1177,6 +1031,10 @@ msgstr "auteur" msgid "is published" msgstr "est publié" +#: com/models.py +msgid "moderator" +msgstr "modérateur" + #: com/models.py msgid "news" msgstr "nouvelle" @@ -1237,6 +1095,10 @@ msgstr "fichier" msgid "display time" msgstr "temps d'affichage" +#: com/models.py core/models.py +msgid "is moderated" +msgstr "est modéré" + #: com/models.py msgid "Begin date should be before end date" msgstr "La date de début doit être avant celle de fin" @@ -1272,46 +1134,6 @@ msgstr "Nouvelle publiée" msgid "News deleted" msgstr "Nouvelle supprimée" -#: com/templates/com/mailing_admin.jinja com/views.py -#: core/templates/core/user_tools.jinja -msgid "Mailing lists administration" -msgstr "Administration des mailing listes" - -#: com/templates/com/mailing_admin.jinja -#: com/templates/com/news_admin_list.jinja com/templates/com/weekmail.jinja -#: counter/templates/counter/refilling_list.jinja -msgid "Actions" -msgstr "Actions" - -#: com/templates/com/mailing_admin.jinja com/templates/com/poster_list.jinja -#: core/templates/core/file_detail.jinja -#: core/templates/core/file_moderation.jinja -#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja -#: sas/templates/sas/moderation.jinja sas/templates/sas/picture.jinja -msgid "Moderate" -msgstr "Modérer" - -#: com/templates/com/mailing_admin.jinja -#, python-format -msgid "Moderated by %(user)s" -msgstr "Modéré par %(user)s" - -#: com/templates/com/mailing_admin.jinja -msgid "This page lists all mailing lists" -msgstr "Cette page liste toutes les listes de diffusion" - -#: com/templates/com/mailing_admin.jinja -msgid "Not moderated mailing lists" -msgstr "Listes de diffusion non modérées" - -#: com/templates/com/mailing_admin.jinja -msgid "Moderated mailing lists" -msgstr "Modérer les listes de diffusion" - -#: com/templates/com/mailing_admin.jinja -msgid "No mailing list existing" -msgstr "Aucune liste de diffusion existante" - #: com/templates/com/news_admin_list.jinja msgid "News admin" msgstr "Administration des nouvelles" @@ -1344,6 +1166,15 @@ msgstr "Titre" msgid "Summary" msgstr "Résumé" +#: com/templates/com/news_admin_list.jinja com/templates/com/weekmail.jinja +#: core/templates/core/user_clubs.jinja +#: counter/templates/counter/invoices_call.jinja +#: trombi/templates/trombi/edit_profile.jinja +#: trombi/templates/trombi/export.jinja +#: trombi/templates/trombi/user_profile.jinja +msgid "Club" +msgstr "Club" + #: com/templates/com/news_admin_list.jinja com/templates/com/weekmail.jinja #: forum/templates/forum/forum.jinja sas/models.py msgid "Author" @@ -1358,6 +1189,11 @@ msgstr "Modérateur" msgid "Dates" msgstr "Dates" +#: com/templates/com/news_admin_list.jinja com/templates/com/weekmail.jinja +#: counter/templates/counter/refilling_list.jinja +msgid "Actions" +msgstr "Actions" + #: com/templates/com/news_admin_list.jinja core/templates/core/file.jinja #: core/templates/core/page/base.jinja msgid "View" @@ -1518,6 +1354,13 @@ msgstr "Créer" msgid "Click to expand" msgstr "Cliquez pour agrandir" +#: com/templates/com/poster_list.jinja core/templates/core/file_detail.jinja +#: core/templates/core/file_moderation.jinja +#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja +#: sas/templates/sas/moderation.jinja sas/templates/sas/picture.jinja +msgid "Moderate" +msgstr "Modérer" + #: com/templates/com/poster_list.jinja msgid "No posters" msgstr "Aucune affiche" @@ -2828,14 +2671,6 @@ msgstr "Clubs actuels : " msgid "Old club(s) :" msgstr "Anciens clubs :" -#: core/templates/core/user_clubs.jinja -msgid "Subscribed mailing lists" -msgstr "Mailing listes abonnées" - -#: core/templates/core/user_clubs.jinja -msgid "Unsubscribe" -msgstr "Se désabonner" - #: core/templates/core/user_detail.jinja #, python-format msgid "%(user_name)s's profile" @@ -3317,6 +3152,10 @@ msgstr "%s est déjà votre fillot/fillote" msgid "Users to add to group" msgstr "Utilisateurs à ajouter au groupe" +#: core/views/group.py +msgid "Search users to add (one or more)." +msgstr "Recherche les utilisateurs à ajouter (un ou plus)." + #: core/views/group.py msgid "Users to remove from group" msgstr "Utilisateurs à retirer du groupe" @@ -3416,6 +3255,10 @@ msgstr "" "temps, mais les utilisateurs suivants ont été définis comme les deux : " "%(users)s" +#: counter/forms.py pedagogy/templates/pedagogy/moderation.jinja +msgid "Action" +msgstr "Action" + #: counter/forms.py msgid "Date and time of action" msgstr "Date et heure de l'action" @@ -5862,10 +5705,6 @@ msgstr "Cursus alternant (-20%)" msgid "A new poster needs to be moderated" msgstr "Une nouvelle affiche a besoin d'être modérée" -#: sith/settings.py -msgid "A new mailing list needs to be moderated" -msgstr "Une nouvelle mailing list a besoin d'être modérée" - #: sith/settings.py msgid "A new pedagogy comment has been signaled for moderation" msgstr "" @@ -5994,6 +5833,10 @@ msgstr "Toutes les cotisations" msgid "Existing member" msgstr "Membre existant" +#: subscription/templates/subscription/subscription.jinja +msgid "New member" +msgstr "Nouveau membre" + #: subscription/views.py msgid "the groups that can create subscriptions" msgstr "les groupes pouvant créer des cotisations" diff --git a/sith/settings.py b/sith/settings.py index 1b81a5c5..ad43323a 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -621,7 +621,6 @@ with open( SITH_NOTIFICATIONS = [ ("POSTER_MODERATION", _("A new poster needs to be moderated")), - ("MAILING_MODERATION", _("A new mailing list needs to be moderated")), ( "PEDAGOGY_MODERATION", _("A new pedagogy comment has been signaled for moderation"),