Add form for inviting people to an event. Allows both invite by email, and directly to team members. Fixes #74

This commit is contained in:
Michael Hall 2018-05-11 23:06:03 -04:00
parent 5626065fe5
commit 376c06200b
7 changed files with 184 additions and 3 deletions

View file

@ -259,6 +259,12 @@ class NewTeamEventForm(forms.ModelForm):
class DeleteEventForm(forms.Form):
confirm = forms.BooleanField(label="Yes, delete event", required=True)
class EventInviteMemberForm(forms.Form):
member = forms.ChoiceField(label=_(""))
class EventInviteEmailForm(forms.Form):
emails = MultiEmailField(label=_(""), widget=forms.widgets.Textarea)
class EventSeriesForm(forms.ModelForm):
class Meta:
model = EventSeries

View file

@ -0,0 +1,13 @@
{% extends "get_together/emails/base.html" %}
{% block content %}
<h3>You've been invited to attend {{event.name|striptags}}</h3>
<p>{{ sender }} has invited you to an event by <b>{{team.name}}</b>.</p>
<h4>{{event.name|striptags}}</h4>
<p>{{event.summary|striptags}}</p>
<br>
<a href="{{event.get_full_url}}" title="{{ event.name|striptags }} page.">View this event.</a>
</p>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% block content %}
== You've been invited to attend {{event.name|striptags}} ==
{{ sender }} has invited you to an event by {{team.name}}
=== {{event.name|striptags}} ===
{{event.summary}}
Click here to view this event: {{event.get_full_url}}
{% endblock %}

View file

@ -0,0 +1,58 @@
{% extends "get_together/base.html" %}
{% load markup tz %}
{% block add_to_title %} | {{event.name}}{% endblock %}
{% block content %}
<div class="fluid-container">
<h2>Invite people to <a href="{{event.get_absolute_url}}">{{ event.name }}</a></h2>
<div class="row">
{% if is_email_confirmed %}
<div class="col-sm-6">
<hr />
<h4>By email</h4>
<p>Add a list of emails, separated by commas</p>
<form action="{% url 'invite-attendees' event.id %}" method="POST">
{% csrf_token %}
{{ email_form.as_p }}
<button type="submit" name="form" value="email" class="btn btn-primary btn-sm">Send Invites</button>
</form>
</div>
{% endif %}
{% if can_edit_team %}
<div class="col-sm-6">
<hr />
<h4>Team members</h4>
{% if member_choice_count > 0 %}
<p>Select team member of members to invite</p>
<form action="{% url 'invite-attendees' event.id %}" method="POST">
{% csrf_token %}
{{ team_form.as_p }}
<button type="submit" name="form" value="team" class="btn btn-primary btn-sm">Invite members</button>
</form>
{% else %}
<div class="alert alert-success">All invitable team members have responded.</div>
{% endif %}
</div>
{% endif %}
{% if not can_edit_team and not is_email_confirmed %}
<div class="col-sm-12">
<div class="alert alert-danger">You can not send invites for this event.</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#id_member").selectmenu();
});
</script>
{% endblock %}

View file

@ -102,6 +102,9 @@
<h2>{{ event.name }}
</h2>
<p class="text-muted">Hosted by <a href="{% url "show-team" team.id %}">{{ team.name }}</a></p>
{% if can_edit_team or is_email_confirmed %}
<a href="{% url 'invite-attendees' event.id %}" class="btn btn-danger btn-sm"><i class="fa fa-envelope"></i> Invite</a>
{% endif %}
{% if settings.SOCIAL_AUTH_TWITTER_KEY %}
<a href="https://twitter.com/intent/tweet?text=I'm+having+a+get+together!%0D{{event.name|urlencode}}&original_referer={{event.get_full_url|urlencode}}&url={{event.get_full_url|urlencode}}&hashtags=gettogether" data-size="large" class="btn btn-twitter btn-sm"><i class="fa fa-twitter"></i> Tweet</a>
{% endif %}
@ -121,7 +124,7 @@
</button>
<div class="dropdown-menu" aria-labelledby="editMenuButton">
<a href="{% url 'edit-event' event.id %}" class="dropdown-item">Event Details</a>
<a href="{% url 'schedule-event-talks' event.id %}" class="dropdown-item">Talks</a>
<a href="{% url 'schedule-event-talks' event.id %}" class="dropdown-item">Manage Talks</a>
</div>
</div>
{% endif %}

View file

@ -79,6 +79,7 @@ urlpatterns = [
path('team/<int:team_id>/+create-event/', views.create_event, name='create-event'),
path('events/<int:event_id>/+edit/', views.edit_event, name='edit-event'),
path('events/<int:event_id>/+attend/', event_views.attend_event, name='attend-event'),
path('events/<int:event_id>/+invite/', views.invite_attendees, name='invite-attendees'),
path('events/<int:event_id>/+delete/', views.delete_event, name='delete-event'),
path('events/<int:event_id>/+add_place/', views.add_place_to_event, name='add-place'),
path('events/<int:event_id>/+comment/', event_views.comment_event, name='comment-event'),

View file

@ -4,8 +4,11 @@ from django.contrib import messages
from django.contrib.auth import logout as logout_user
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.http import HttpResponse, JsonResponse
from django.contrib.sites.models import Site
from django.utils import timezone
from django.core.mail import send_mail
from django.template.loader import get_template, render_to_string
from django.conf import settings
from events.models.events import (
Event,
@ -28,7 +31,9 @@ from events.forms import (
EventCommentForm,
NewPlaceForm,
UploadEventPhotoForm,
NewCommonEventForm
NewCommonEventForm,
EventInviteEmailForm,
EventInviteMemberForm,
)
from events import location
@ -68,6 +73,8 @@ def show_event(request, event_id, event_slug):
'presentation_list': event.presentations.filter(status=Presentation.ACCEPTED).order_by('start_time'),
'pending_presentations': event.presentations.filter(status=Presentation.PROPOSED).count(),
'can_edit_event': request.user.profile.can_edit_event(event),
'can_edit_team': request.user.profile.can_edit_team(event.team),
'is_email_confirmed': request.user.account.is_email_confirmed,
}
return render(request, 'get_together/events/show_event.html', context)
@ -136,6 +143,88 @@ def create_event(request, team_id):
else:
return redirect('home')
@login_required
def invite_attendees(request, event_id):
event = get_object_or_404(Event, id=event_id)
attendee_userids = [attendee.user.id for attendee in Attendee.objects.filter(event=event)]
members = Member.objects.filter(team=event.team, ).order_by('user__realname')
member_choices = [(member.id, member.user) for member in members if member.user.user.account.is_email_confirmed and member.user.id not in attendee_userids]
default_choices = [('all', 'All Members (%s)' % len(member_choices))]
if request.method == 'POST' and request.POST.get('form', None) == 'email':
email_form = EventInviteEmailForm(request.POST)
if email_form.is_valid():
to = email_form.cleaned_data['emails']
for email in to:
invite_attendee(email, event, request.user.profile)
messages.add_message(request, messages.SUCCESS, message=_('Sent %s invites' % len(to)))
return redirect(event.get_absolute_url())
team_form = EventInviteMemberForm()
team_form.fields['member'].choices = default_choices + member_choices
elif request.method == 'POST' and request.POST.get('form', None) == 'team':
team_form = EventInviteMemberForm(request.POST)
team_form.fields['member'].choices = default_choices + member_choices
if team_form.is_valid():
to = team_form.cleaned_data['member']
if to == 'all':
for (member_id, user) in member_choices:
try:
attendee = Attendee.objects.get(event=event, user=user)
except:
# No attendee record found, so send the invite
invite_attendee(user.user.email, event, request.user.profile)
messages.add_message(request, messages.SUCCESS, message=_('Sent %s invites' % len(member_choices)))
return redirect(event.get_absolute_url())
else:
member = get_object_or_404(Member, id=to)
try:
attendee = Attendee.objects.get(event=event, user=member.user)
except:
# No attendee record found, so send the invite
invite_attendee(member.user.user.email, event, request.user.profile)
messages.add_message(request, messages.SUCCESS, message=_('Invited %s' % member.user))
return redirect(event.get_absolute_url())
email_form = EventInviteEmailForm()
else:
email_form = EventInviteEmailForm()
team_form = EventInviteMemberForm()
team_form.fields['member'].choices = default_choices + member_choices
context = {
'event': event,
'email_form': email_form,
'team_form': team_form,
'member_choice_count': len(member_choices),
'can_edit_team': request.user.profile.can_edit_team(event.team),
'is_email_confirmed': request.user.account.is_email_confirmed,
}
return render(request, 'get_together/events/invite_attendees.html', context)
def invite_attendee(email, event, sender):
context = {
'sender': sender,
'team': event.team,
'event': event,
'site': Site.objects.get(id=1),
}
email_subject = '[GetTogether] Invite to attend %s' % event.name
email_body_text = render_to_string('get_together/emails/attendee_invite.txt', context)
email_body_html = render_to_string('get_together/emails/attendee_invite.html', context)
email_recipients = [email]
email_from = getattr(settings, 'DEFAULT_FROM_EMAIL', 'noreply@gettogether.community')
send_mail(
from_email=email_from,
html_message=email_body_html,
message=email_body_text,
recipient_list=email_recipients,
subject=email_subject,
fail_silently=True,
)
@login_required
def add_event_photo(request, event_id):
event = get_object_or_404(Event, id=event_id)