From 83ef285f8f103d4a71d480a4bd5904251f263557 Mon Sep 17 00:00:00 2001
From: Michael Hall
Date: Wed, 16 May 2018 21:30:32 -0400
Subject: [PATCH] Add ability for an event host to view and contact attendees.
Add ability for an event host to mark if an attendee actually attended or not
after the event is over. Fixes #71
---
events/forms.py | 4 +
.../0030_add_attendee_actual_status.py | 23 ++++
events/models/events.py | 11 +-
.../get_together/emails/attendee_contact.html | 13 ++
.../get_together/emails/attendee_contact.txt | 11 ++
.../get_together/events/manage_attendees.html | 130 ++++++++++++++++++
.../get_together/events/show_event.html | 7 +-
get_together/urls.py | 2 +
get_together/views/events.py | 129 +++++++++++++++++
9 files changed, 327 insertions(+), 3 deletions(-)
create mode 100644 events/migrations/0030_add_attendee_actual_status.py
create mode 100644 get_together/templates/get_together/emails/attendee_contact.html
create mode 100644 get_together/templates/get_together/emails/attendee_contact.txt
create mode 100644 get_together/templates/get_together/events/manage_attendees.html
diff --git a/events/forms.py b/events/forms.py
index 52bb0d2..9fb7def 100644
--- a/events/forms.py
+++ b/events/forms.py
@@ -265,6 +265,10 @@ class EventInviteMemberForm(forms.Form):
class EventInviteEmailForm(forms.Form):
emails = MultiEmailField(label=_(""), widget=forms.widgets.Textarea)
+class EventContactForm(forms.Form):
+ to = forms.ChoiceField(label=_(""))
+ body = forms.CharField(label=_(""), widget=forms.widgets.Textarea)
+
class EventSeriesForm(forms.ModelForm):
class Meta:
model = EventSeries
diff --git a/events/migrations/0030_add_attendee_actual_status.py b/events/migrations/0030_add_attendee_actual_status.py
new file mode 100644
index 0000000..1793bf9
--- /dev/null
+++ b/events/migrations/0030_add_attendee_actual_status.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.0 on 2018-05-17 00:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0029_add_team_premium_fields'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='attendee',
+ name='actual',
+ field=models.SmallIntegerField(choices=[(-1, 'No'), (0, 'Maybe'), (1, 'Yes')], db_index=True, default=0, verbose_name='Attended'),
+ ),
+ migrations.AlterField(
+ model_name='attendee',
+ name='status',
+ field=models.SmallIntegerField(choices=[(-1, 'No'), (0, 'Maybe'), (1, 'Yes')], db_index=True, default=1, verbose_name='Attending'),
+ ),
+ ]
diff --git a/events/models/events.py b/events/models/events.py
index 2115cea..3f2ff13 100644
--- a/events/models/events.py
+++ b/events/models/events.py
@@ -77,6 +77,10 @@ class Event(models.Model):
attendees = models.ManyToManyField(UserProfile, through='Attendee', related_name="attending", blank=True)
+ @property
+ def is_over(self):
+ return self.end_time <= timezone.now()
+
@property
def tz(self):
if self.place is not None:
@@ -210,7 +214,8 @@ class Attendee(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
role = models.SmallIntegerField(_("Role"), choices=ROLES, default=NORMAL, db_index=True)
- status = models.SmallIntegerField(_("Attending?"), choices=STATUSES, default=YES, db_index=True)
+ status = models.SmallIntegerField(_("Attending"), choices=STATUSES, default=YES, db_index=True)
+ actual = models.SmallIntegerField(_("Attended"), choices=STATUSES, default=MAYBE, db_index=True)
joined_date = models.DateTimeField(default=timezone.now)
last_reminded = models.DateTimeField(null=True, blank=True)
@@ -222,6 +227,10 @@ class Attendee(models.Model):
def status_name(self):
return Attendee.STATUSES[self.status+1][1]
+ @property
+ def actual_name(self):
+ return Attendee.STATUSES[self.actual+1][1]
+
def __str__(self):
return "%s at %s" % (self.user, self.event)
diff --git a/get_together/templates/get_together/emails/attendee_contact.html b/get_together/templates/get_together/emails/attendee_contact.html
new file mode 100644
index 0000000..d74e7ea
--- /dev/null
+++ b/get_together/templates/get_together/emails/attendee_contact.html
@@ -0,0 +1,13 @@
+{% extends "get_together/emails/base.html" %}
+
+{% block content %}
+Message about {{event.name|striptags}}
+
+Sender : {{ sender|striptags }}
+
+{{body|striptags}}
+
+
+Go to the event page.
+
+{% endblock %}
diff --git a/get_together/templates/get_together/emails/attendee_contact.txt b/get_together/templates/get_together/emails/attendee_contact.txt
new file mode 100644
index 0000000..827eb40
--- /dev/null
+++ b/get_together/templates/get_together/emails/attendee_contact.txt
@@ -0,0 +1,11 @@
+{% extends 'get_together/emails/base.txt' %}
+{% block content %}
+== Message about {{event.name}} ==
+
+Sender: {{ sender }}
+
+{{ body|striptags }}
+
+Event page: {{event.get_full_url}}
+
+{% endblock %}
diff --git a/get_together/templates/get_together/events/manage_attendees.html b/get_together/templates/get_together/events/manage_attendees.html
new file mode 100644
index 0000000..a1fc9fa
--- /dev/null
+++ b/get_together/templates/get_together/events/manage_attendees.html
@@ -0,0 +1,130 @@
+{% extends "get_together/base.html" %}
+{% load static markup tz %}
+
+{% block add_to_title %} | {{team.name}}{% endblock %}
+
+{% block styles %}
+
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
{{attendees.count}} Attendees for {{ event.name }}
+
+
Invite Attendees
+
+
+
+ {% for attendee in attendees %}
+
+
+
+
+
+
+ {% if event.is_over and attendee.actual != attendee.MAYBE %}
+ {% if attendee.actual == attendee.YES %}
+
{{ attendee.actual_name }}
+ {% elif attendee.actual == attendee.NO %}
+
{{ attendee.actual_name }}
+ {% endif %}
+ {% else %}
+ {% if attendee.status == attendee.YES %}
+
{{ attendee.status_name }}
+ {% elif attendee.status == attendee.NO %}
+
{{ attendee.status_name }}
+ {% elif attendee.status == attendee.MAYBE %}
+
{{ attendee.status_name }}
+ {% endif %}
+ {% endif %}
+
+
+
+
{{attendee.user}}
+ {% if attendee.user.user.account.is_email_confirmed %}
+
+ {% endif %}
+
+ {% if event.is_over %}
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block javascript %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/get_together/templates/get_together/events/show_event.html b/get_together/templates/get_together/events/show_event.html
index 12edde8..0e97571 100644
--- a/get_together/templates/get_together/events/show_event.html
+++ b/get_together/templates/get_together/events/show_event.html
@@ -114,7 +114,7 @@
{% if settings.SOCIAL_AUTH_LINKEDIN_KEY %}
Share
{% endif %}
- {% if not is_attending %}
+ {% if not event.is_over and not is_attending %}
{% endif %}
@@ -183,7 +184,9 @@
{% for presentation in presentation_list %}
{% endfor %}
+ {% if not event.is_over %}
Propose a talk
+ {% endif %}
{% if pending_presentations and can_edit_event %}
{{pending_presentations}} proposed talks
{% endif %}
@@ -250,7 +253,7 @@
{{attendee.user}}
- {% if attendee.user.user == request.user %}
+ {% if attendee.user.user == request.user and not event.is_over %}
{% if attendee.status == attendee.YES %}
{{ attendee.status_name }}