loko/streetup/notifications/forms.py

154 lines
5.4 KiB
Python

from django import forms
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from common.models import UserConfig
from .models import Notification, Team
class MultipleFileInput(forms.FileInput):
"""Widget FileInput autorisant la sélection de plusieurs fichiers."""
allow_multiple_selected = True
def __init__(self, attrs=None):
super().__init__(attrs={'multiple': True, 'class': 'form-control', **(attrs or {})})
class MultipleFileField(forms.FileField):
"""Champ fichier acceptant plusieurs fichiers."""
widget = MultipleFileInput
def clean(self, data, initial=None):
# data may be a list (multiple files) or a single file
if not data:
return []
if not isinstance(data, list):
data = [data]
return [super(MultipleFileField, self).clean(d, initial) for d in data]
class NotificationCreateForm(forms.Form):
"""Formulaire de création manuelle d'une notification."""
title = forms.CharField(
max_length=255,
label=_("Titre"),
widget=forms.TextInput(attrs={'class': 'form-control'}),
)
content = forms.CharField(
required=False,
label=_("Contenu"),
widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}),
)
notification_type = forms.ChoiceField(
choices=Notification.TYPES,
initial=Notification.TYPE_MESSAGE,
label=_("Type"),
widget=forms.Select(attrs={'class': 'form-select'}),
)
action_url = forms.CharField(
required=False,
max_length=500,
label=_("Lien d'action (URL)"),
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '/example/path/'}),
)
action_label = forms.CharField(
required=False,
max_length=100,
label=_("Libellé du lien"),
widget=forms.TextInput(attrs={'class': 'form-control'}),
)
expires_at = forms.DateTimeField(
required=False,
label=_("Expire le"),
widget=forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}),
)
attachments = MultipleFileField(
required=False,
label=_("Pièces jointes"),
help_text=_("Photos ou documents (plusieurs fichiers possibles)."),
)
# Recipients
recipient_users = forms.ModelMultipleChoiceField(
queryset=User.objects.filter(is_active=True).order_by('first_name', 'last_name', 'username'),
required=False,
label=_("Destinataires individuels"),
widget=forms.SelectMultiple(attrs={'class': 'form-select', 'size': '6'}),
)
recipient_teams = forms.ModelMultipleChoiceField(
queryset=Team.objects.all(),
required=False,
label=_("Équipes destinataires"),
widget=forms.SelectMultiple(attrs={'class': 'form-select', 'size': '4'}),
)
def clean(self):
cleaned_data = super().clean()
users = cleaned_data.get('recipient_users')
teams = cleaned_data.get('recipient_teams')
if not users and not teams:
raise forms.ValidationError(
_("Veuillez sélectionner au moins un destinataire ou une équipe.")
)
return cleaned_data
class TeamForm(forms.ModelForm):
class Meta:
model = Team
fields = ['name', 'description', 'members']
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'members': forms.SelectMultiple(attrs={'class': 'form-select', 'size': '8'}),
}
class NotificationReminderSettingsForm(forms.ModelForm):
class Meta:
model = UserConfig
fields = [
'preferred_language',
'notification_reminder_enabled',
'notification_reminder_emails',
'notification_reminder_delay_hours',
]
widgets = {
'preferred_language': forms.Select(
attrs={'class': 'form-select rounded-3'}
),
'notification_reminder_enabled': forms.CheckboxInput(
attrs={'class': 'form-check-input', 'role': 'switch'}
),
'notification_reminder_emails': forms.TextInput(
attrs={
'class': 'form-control rounded-3',
'placeholder': _("Ex: email1@exemple.com, email2@exemple.com"),
}
),
'notification_reminder_delay_hours': forms.NumberInput(
attrs={'class': 'form-control rounded-3', 'min': 1, 'max': 720}
),
}
def clean_notification_reminder_emails(self):
emails_raw = self.cleaned_data.get('notification_reminder_emails', '')
if not emails_raw:
return ''
import re
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
cleaned_emails = []
for email in re.split(r'[;,]', emails_raw):
email = email.strip()
if email:
try:
validate_email(email)
cleaned_emails.append(email)
except ValidationError:
raise forms.ValidationError(
_("L'adresse e-mail '%(email)s' n'est pas valide.") % {'email': email}
)
return ', '.join(cleaned_emails)