members/waitinglist: allow editing of invite text

pull/94/head
Christian Merten 12 months ago
parent c2bfd85eb4
commit 31b31a3eb3
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -26,7 +26,7 @@ GROUP_TIME_AVAILABLE_TEXT = """Die Gruppenstunde findet jeden {weekday} von {sta
GROUP_TIME_UNAVAILABLE_TEXT = """Bitte erfrage die Gruppenzeiten bei der Gruppenleitung ({contact_email})."""
INVITE_TEXT = """Hallo {name},
INVITE_TEXT = """Hallo {{name}},
wir haben gute Neuigkeiten für dich. Es ist ein Platz in der Jugendgruppe {group_name} {group_link}freigeworden.
{group_time}
@ -38,7 +38,7 @@ Informationen und deine Anmeldebestätigung von dir. Die lädst du herunter
(siehe %(REGISTRATION_FORM_DOWNLOAD_LINK)s ), lässt sie von deinen Eltern ausfüllen, unterschreiben
und lädst ein Foto davon in unserem Anmeldeformular hoch. Das kannst du alles über folgenden Link erledigen:
{link}
{{link}}
Du siehst dort auch die Daten, die du bei deiner Eintragung auf die Warteliste angegeben hast. Bitte
überprüfe, ob die Daten noch stimmen und ändere sie bei Bedarf ab.
@ -46,7 +46,7 @@ Du siehst dort auch die Daten, die du bei deiner Eintragung auf die Warteliste a
Falls du zu dem obigen Termin keine Zeit hast oder dich ganz von der Warteliste abmelden möchtest,
lehne bitte diese Einladung unter folgendem Link ab:
{invitation_reject_link}
{{invitation_reject_link}}
Bei Fragen, wende dich gerne an %(RESPONSIBLE_MAIL)s.

@ -561,6 +561,12 @@ class WaiterInviteForm(forms.Form):
label=_('Group'))
class WaiterInviteTextForm(forms.Form):
_selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
text_template = forms.CharField(label=_('Invitation text'),
widget=forms.Textarea(attrs={'rows': 30, 'cols': 100}))
class InvitationToGroupAdmin(admin.TabularInline):
model = InvitationToGroup
fields = ['group', 'date', 'status']
@ -594,7 +600,7 @@ class MemberWaitingListAdmin(CommonAdminMixin, admin.ModelAdmin):
'confirmed_mail', 'waiting_confirmed', 'sent_reminders')
search_fields = ('prename', 'lastname', 'email')
list_filter = ['confirmed_mail', 'gender', InvitedToGroupFilter]
actions = ['ask_for_registration', 'ask_for_wait_confirmation']
actions = ['ask_for_registration_action', 'ask_for_wait_confirmation']
inlines = [InvitationToGroupAdmin]
readonly_fields= ['application_date', 'sent_reminders']
@ -609,38 +615,6 @@ class MemberWaitingListAdmin(CommonAdminMixin, admin.ModelAdmin):
_("Successfully asked %(name)s to confirm their waiting status.") % {'name': waiter.name})
ask_for_wait_confirmation.short_description = _('Ask selected waiters to confirm their waiting status')
def ask_for_registration(self, request, queryset):
"""Asks the waiting person to register with all required data."""
if "apply" in request.POST:
try:
group = Group.objects.get(pk=request.POST['group'])
except Group.DoesNotExist:
messages.error(request,
_("An error occurred while trying to invite said members. Please try again."))
return HttpResponseRedirect(request.get_full_path())
if not group.contact_email:
messages.error(request,
_('The selected group does not have a contact email. Please first set a contact email and then try again.'))
return HttpResponseRedirect(request.get_full_path())
for waiter in queryset:
waiter.invited_for_group = group
waiter.save()
waiter.invite_to_group(group)
messages.success(request,
_("Successfully invited %(name)s to %(group)s.") % {'name': waiter.name, 'group': waiter.invited_for_group.name})
return HttpResponseRedirect(request.get_full_path())
context = dict(self.admin_site.each_context(request),
title=_('Select group for invitation'),
opts=self.opts,
waiters=queryset.all(),
form=WaiterInviteForm(initial={'_selected_action': queryset.values_list('id', flat=True)}))
return render(request,
'admin/invite_selected_for_group.html',
context=context)
ask_for_registration.short_description = _('Offer waiter a place in a group.')
def response_change(self, request, waiter):
ret = super(MemberWaitingListAdmin, self).response_change(request, waiter)
if "_invite" in request.POST:
@ -672,8 +646,19 @@ class MemberWaitingListAdmin(CommonAdminMixin, admin.ModelAdmin):
queryset = super().get_queryset(request)
return queryset.prefetch_related('invitationtogroup_set')
def ask_for_registration_action(self, request, queryset):
return self.invite_view(request, queryset)
ask_for_registration_action.short_description = _('Offer waiter a place in a group.')
def invite_view(self, request, object_id):
if type(object_id) == str:
waiter = MemberWaitingList.objects.get(pk=object_id)
queryset = [waiter]
id_list = [waiter.pk]
else:
waiter = None
queryset = object_id
id_list = queryset.values_list('id', flat=True)
if "apply" in request.POST:
try:
@ -687,22 +672,49 @@ class MemberWaitingListAdmin(CommonAdminMixin, admin.ModelAdmin):
messages.error(request,
_('The selected group does not have a contact email. Please first set a contact email and then try again.'))
return HttpResponseRedirect(request.get_full_path())
context = dict(self.admin_site.each_context(request),
title=_('Select group for invitation'),
opts=self.opts,
group=group,
queryset=queryset,
form=WaiterInviteTextForm(initial={
'_selected_action': id_list,
'text_template': group.get_invitation_text_template()
}))
if waiter:
context = dict(context, object=waiter, waiter=waiter)
return render(request,
'admin/invite_for_group_text.html',
context=context)
waiter.invited_for_group = group
waiter.save()
waiter.invite_to_group(group)
if "send" in request.POST:
try:
group = Group.objects.get(pk=request.POST['group'])
text_template = request.POST['text_template']
except (Group.DoesNotExist, KeyError):
messages.error(request,
_("An error occurred while trying to invite said members. Please try again."))
return HttpResponseRedirect(request.get_full_path())
for w in queryset:
w.invite_to_group(group, text_template=text_template)
messages.success(request,
_("Successfully invited %(name)s to %(group)s.") % {'name': waiter.name, 'group': waiter.invited_for_group.name})
_("Successfully invited %(name)s to %(group)s.") % {'name': w.name, 'group': w.invited_for_group.name})
return HttpResponseRedirect(reverse('admin:%s_%s_change' % (waiter._meta.app_label, waiter._meta.model_name),
if waiter:
return HttpResponseRedirect(reverse('admin:%s_%s_change' % (self.opts.app_label, self.opts.model_name),
args=(object_id,)))
else:
return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name)))
context = dict(self.admin_site.each_context(request),
title=_('Select group for invitation'),
opts=self.opts,
object=waiter,
waiter=waiter,
form=WaiterInviteForm(initial={'_selected_action': [waiter.pk]}))
queryset=queryset,
form=WaiterInviteForm(initial={
'_selected_action': id_list
}))
if waiter:
context = dict(context, object=waiter, waiter=waiter)
return render(request,
'admin/invite_for_group.html',
context=context)

File diff suppressed because it is too large Load Diff

@ -97,6 +97,24 @@ class Group(models.Model):
# return if the group has all relevant time slot information filled
return self.weekday and self.start_time and self.end_time
def get_invitation_text_template(self):
"""The text template used to invite waiters to this group. This contains
placeholders for the name of the waiter and personalized links."""
if self.show_website:
group_link = '({url}) '.format(url=prepend_base_url(reverse('startpage:gruppe_detail', args=[self.name])))
else:
group_link = ''
if self.has_time_info():
group_time = settings.GROUP_TIME_AVAILABLE_TEXT.format(weekday=WEEKDAYS[self.weekday][1],
start_time=self.start_time.strftime('%H:%M'),
end_time=self.end_time.strftime('%H:%M'))
else:
group_time = settings.GROUP_TIME_UNAVAILABLE_TEXT.format(contact_email=self.contact_email)
return settings.INVITE_TEXT.format(group_time=group_time,
group_name=self.name,
group_link=group_link,
contact_email=self.contact_email)
class MemberManager(models.Manager):
def get_queryset(self):
@ -945,25 +963,19 @@ class MemberWaitingList(Person):
except InvitationToGroup.DoesNotExist:
return False
def invite_to_group(self, group):
if group.show_website:
group_link = '({url}) '.format(url=prepend_base_url(reverse('startpage:gruppe_detail', args=[group.name])))
else:
group_link = ''
if group.has_time_info():
group_time = settings.GROUP_TIME_AVAILABLE_TEXT.format(weekday=WEEKDAYS[group.weekday][1],
start_time=group.start_time.strftime('%H:%M'),
end_time=group.end_time.strftime('%H:%M'))
else:
group_time = settings.GROUP_TIME_UNAVAILABLE_TEXT.format(contact_email=group.contact_email)
def invite_to_group(self, group, text_template=None):
"""
Invite waiter to given group. Stores a new group invitation
and sends a personalized e-mail based on the passed template.
"""
self.invited_for_group = group
self.save()
if not text_template:
text_template = group.get_invitation_text_template()
invitation = InvitationToGroup(group=group, waiter=self)
invitation.save()
self.send_mail(_("Invitation to trial group meeting"),
settings.INVITE_TEXT.format(name=self.prename,
group_time=group_time,
group_name=group.name,
group_link=group_link,
contact_email=group.contact_email,
text_template.format(name=self.prename,
link=get_registration_link(invitation.key),
invitation_reject_link=get_invitation_reject_link(invitation.key)),
cc=group.contact_email.email)

@ -17,7 +17,9 @@
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
{% if object %}
&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
{% endif %}
&rsaquo; {% translate 'Invite to group' %}
</div>
{% endblock %}
@ -25,18 +27,28 @@
{% block content %}
<h2>{% translate "Invite to a group" %}</h2>
<p>
{% if waiter %}
{% trans "You are inviting:" %}
{% else %}
{% trans "You are inviting the following waiters for registration:" %}
{% endif %}
</p>
<p>
<ul>
{% for waiter in queryset %}
<li>
<a href="{% url 'admin:members_memberwaitinglist_change' waiter.id %}">{{ waiter }}</a>
</li>
{% endfor %}
</ul>
</p>
<p>
{% if waiter %}
{% blocktrans %}Please choose the group that you want to invite {{ waiter }} to.{% endblocktrans %}
{% else %}
{% blocktrans %}To which group do you want to invite these waiters?{% endblocktrans %}
{% endif %}
</p>
<form action="" method="post">
@ -47,7 +59,7 @@
<br>
<div>
<p>
<input type="hidden" name="action" value="ask_for_registration">
<input type="hidden" name="action" value="ask_for_registration_action">
<input class="default" style="color: $default-link-color" type="submit" name="apply" value="{% translate 'Invite' %}">
<a href="#" class="button cancel-link">{% translate "Cancel" %}</a>
</p>

@ -0,0 +1,68 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static %}
{% block extrahead %}
{{ block.super }}
{{ media }}
<script src="{% static 'admin/js/cancel.js' %}" async></script>
<script type="text/javascript" src="{% static "admin/js/vendor/jquery/jquery.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script>
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} invite-waiter
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
{% if object %}
&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
{% endif %}
&rsaquo; {% translate 'Invite to group' %}
</div>
{% endblock %}
{% block content %}
<h2>{% translate "Invite to a group" %}</h2>
<p>
{% if waiter %}
{% blocktrans %}You are inviting the following waiter for registration in group {{ group }}.{% endblocktrans %}
{% else %}
{% blocktrans %}You are inviting the following waiters for registration in group {{ group }}.{% endblocktrans %}
{% endif %}
</p>
<p>
<ul>
{% for waiter in queryset %}
<li>
<a href="{% url 'admin:members_memberwaitinglist_change' waiter.id %}">{{ waiter }}</a>
</li>
{% endfor %}
</ul>
</p>
<p>
{% blocktrans %}The following text will be sent as an invitation email. The patterns
{name}, {link} and {invitation_reject_link} will be automatically replaced by personalized
data upon sending. Please adapt if needed and confirm.{% endblocktrans %}
</p>
<form action="" method="post">
{% csrf_token %}
<p>
{{form}}
</p>
<br>
<div>
<p>
<input type="hidden" name="group" value="{{ group.pk }}">
<input type="hidden" name="action" value="ask_for_registration_action">
<input class="default" style="color: $default-link-color" type="submit" name="send" value="{% translate 'Send' %}">
<a href="#" class="button cancel-link">{% translate "Back" %}</a>
</p>
</div>
</form>
{% endblock %}
Loading…
Cancel
Save