diff --git a/cfp/emails.py b/cfp/emails.py index a4ca517..2d65430 100644 --- a/cfp/emails.py +++ b/cfp/emails.py @@ -5,7 +5,7 @@ from pprint import pformat from textwrap import indent from mailing.utils import send_message -from .environment import TalkEnvironment, SpeakerEnvironment +from .environment import TalkEnvironment, SpeakerEnvironment, VolunteerEnvironment def talk_email_render_preview(talk, speaker, subject, body): @@ -40,6 +40,22 @@ def speaker_email_render_preview(speaker, subject, body): return preview +def volunteer_email_render_preview(volunteer, subject, body): + env = VolunteerEnvironment(volunteer) + try: + subject = env.from_string(subject).render() + except Exception: + return _('There is an error in your subject template.') + try: + body = env.from_string(body).render() + except Exception: + return _('There is an error in your body template.') + context = {'volunteer': env.globals['volunteer']} + preview = '' + _('Environment:') + '\n\n' + escape(indent(pformat(context, indent='2'), ' ')) + preview += '\n\n' + _('Subject:') + ' ' + escape(subject) + '\n' + _('Body:') + '\n' + escape(body) + return preview + + def talk_email_send(talks, subject, body): sent = 0 for talk in talks.all(): @@ -61,3 +77,14 @@ def speaker_email_send(speakers, subject, body): send_message(speaker.conversation, speaker.site.conference, subject=s, content=c) sent += 1 return sent + + +def volunteer_email_send(volunteers, subject, body): + sent = 0 + for volunteer in volunteers.all(): + env = VolunteerEnvironment(volunteer) + s = env.from_string(subject).render() + c = env.from_string(body).render() + send_message(volunteer.conversation, volunteer.site.conference, subject=s, content=c) + sent += 1 + return sent diff --git a/cfp/environment.py b/cfp/environment.py index 0a527cf..1b0134f 100644 --- a/cfp/environment.py +++ b/cfp/environment.py @@ -32,6 +32,16 @@ def speaker_to_dict(speaker, include_talks=False): return d +def volunteer_to_dict(volunteer): + return { + 'name': volunteer.name, + 'email': volunteer.email, + 'phone_number': volunteer.phone_number, + 'sms_prefered': volunteer.sms_prefered, + 'activities': list(map(lambda activity: activity.name, volunteer.activities.all())), + } + + class TalkEnvironment(SandboxedEnvironment): def __init__(self, talk, speaker, **options): super().__init__(**options) @@ -47,3 +57,11 @@ class SpeakerEnvironment(SandboxedEnvironment): self.globals.update({ 'speaker': speaker_to_dict(speaker, include_talks=True), }) + + +class VolunteerEnvironment(SandboxedEnvironment): + def __init__(self, volunteer, **options): + super().__init__(**options) + self.globals.update({ + 'volunteer': volunteer_to_dict(volunteer), + }) diff --git a/cfp/forms.py b/cfp/forms.py index ead8095..c5127e1 100644 --- a/cfp/forms.py +++ b/cfp/forms.py @@ -11,7 +11,7 @@ from django_select2.forms import ModelSelect2MultipleWidget from .models import Participant, Talk, TalkCategory, Track, Tag, \ Conference, Room, Volunteer, Activity -from .environment import TalkEnvironment, SpeakerEnvironment +from .environment import TalkEnvironment, SpeakerEnvironment, VolunteerEnvironment ACCEPTATION_CHOICES = [ @@ -216,6 +216,16 @@ class SpeakerActionForm(forms.Form): self.fields['speakers'].choices = [(speaker.pk, None) for speaker in speakers.all()] +class VolunteerActionForm(forms.Form): + volunteers = forms.MultipleChoiceField(choices=[]) + email = forms.BooleanField(required=False, label=_('Send an email')) + + def __init__(self, *args, **kwargs): + volunteers = kwargs.pop('volunteers') + super().__init__(*args, **kwargs) + self.fields['volunteers'].choices = [(volunteer.pk, None) for volunteer in volunteers.all()] + + class NotifyForm(forms.Form): notify = forms.BooleanField(initial=True, required=False, label=_('Notify by mail?')) @@ -283,22 +293,31 @@ class PreviewSpeakerMailForm(forms.Form): body = forms.CharField(required=False, label=_('Body')) -class SendTalkMailForm(forms.Form): +class PreviewVolunteerMailForm(forms.Form): + volunteer = forms.IntegerField() + subject = forms.CharField(required=False, label=_('Subject')) + body = forms.CharField(required=False, label=_('Body')) + + +class SendMailForm(forms.Form): subject = forms.CharField() body = forms.CharField(widget=forms.Textarea) confirm = forms.BooleanField(required=False, label=_('I read my self twice, confirm sending')) - def __init__(self, *args, **kwargs): - self._talks = kwargs.pop('talks') - super().__init__(*args, **kwargs) - self._env = dict() - def clean_subject(self): return self.clean_template('subject') def clean_body(self): return self.clean_template('body') + + +class SendTalkMailForm(SendMailForm): + def __init__(self, *args, **kwargs): + self._talks = kwargs.pop('talks') + super().__init__(*args, **kwargs) + self._env = dict() + def clean_template(self, template): try: for talk in self._talks.all(): @@ -311,22 +330,12 @@ class SendTalkMailForm(forms.Form): return self.cleaned_data.get(template) -class SendSpeakerMailForm(forms.Form): - subject = forms.CharField() - body = forms.CharField(widget=forms.Textarea) - confirm = forms.BooleanField(required=False, label=_('I read my self twice, confirm sending')) - +class SendSpeakerMailForm(SendMailForm): def __init__(self, *args, **kwargs): self._speakers = kwargs.pop('speakers') super().__init__(*args, **kwargs) self._env = dict() - def clean_subject(self): - return self.clean_template('subject') - - def clean_body(self): - return self.clean_template('body') - def clean_template(self, template): try: for speaker in self._speakers.all(): @@ -338,6 +347,23 @@ class SendSpeakerMailForm(forms.Form): return self.cleaned_data.get(template) +class SendVolunteerMailForm(SendMailForm): + def __init__(self, *args, **kwargs): + self._volunteers = kwargs.pop('volunteers') + super().__init__(*args, **kwargs) + self._env = dict() + + def clean_template(self, template): + try: + for volunteer in self._volunteers.all(): + env = self._env.get(volunteer, VolunteerEnvironment(volunteer)) + env.from_string(self.cleaned_data.get(template)).render() + except Exception as e: + raise forms.ValidationError(_("Your template does not compile (at least) with volunteer '%(volunteer)s'.") % + {'volunteer': volunteer}) + return self.cleaned_data.get(template) + + class UsersWidget(ModelSelect2MultipleWidget): model = User search_fields = [ '%s__icontains' % field for field in UserAdmin.search_fields ] diff --git a/cfp/templates/cfp/staff/speaker_email.html b/cfp/templates/cfp/staff/speaker_email.html index 28f729d..1c44d3a 100644 --- a/cfp/templates/cfp/staff/speaker_email.html +++ b/cfp/templates/cfp/staff/speaker_email.html @@ -16,7 +16,7 @@
{% blocktrans %}You can use Jinja2 templating language.{% endblocktrans %} - {% blocktrans %}To see available environment variables, please click on a talk and speaker combination.{% endblocktrans %} + {% blocktrans %}To see available environment variables, please click on a speaker.{% endblocktrans %}
+ + {% trans "Show filtering options…" %} + +