Display and allow updating bulletin subscriptions

This commit is contained in:
Yingtong Li 2019-01-26 12:48:49 +11:00
parent 62ebe96520
commit bc2cb70aec
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
5 changed files with 109 additions and 8 deletions

View File

@ -31,6 +31,7 @@ def environment(**options):
env.globals.update({ env.globals.update({
'import': importlib.import_module, # forgive me for I have sinned 'import': importlib.import_module, # forgive me for I have sinned
'localtime': lambda dt: timezone.localtime(dt).strftime('%Y-%m-%d %H:%M'), 'localtime': lambda dt: timezone.localtime(dt).strftime('%Y-%m-%d %H:%M'),
'settings': settings,
'static': staticfiles_storage.url, 'static': staticfiles_storage.url,
'url': reverse, 'url': reverse,
'MEDIA_URL': settings.MEDIA_URL, 'MEDIA_URL': settings.MEDIA_URL,

View File

@ -71,7 +71,7 @@
<a class="ui card" href="{{ url('membership') }}"> <a class="ui card" href="{{ url('membership') }}">
<div class="content"> <div class="content">
<div class="header">Membership Portal</div> <div class="header">Membership Portal</div>
<div class="description">View and update your membership details.</div> <div class="description">View and update your membership details. Update your bulletin subscription.</div>
</div> </div>
<div class="ui bottom attached primary button"> <div class="ui bottom attached primary button">
<i class="chevron right icon" style="margin: 0 .42857143em 0 -.21428571em;"></i> <i class="chevron right icon" style="margin: 0 .42857143em 0 -.21428571em;"></i>

View File

@ -26,7 +26,7 @@
<h1>Membership details</h1> <h1>Membership details</h1>
<form class="ui form" method="POST" action="{{ url('membership') }}"> <form class="ui form" method="POST" action="{{ url('membership') }}">
<div class="ui required inline grid field"> <div class="ui disabled inline grid field">
<label class="three wide column">Member number</label> <label class="three wide column">Member number</label>
<div class="nine wide column">{{ member.id }}</div> <div class="nine wide column">{{ member.id }}</div>
</div> </div>
@ -35,7 +35,7 @@
<label class="three wide column">Student ID</label> <label class="three wide column">Student ID</label>
<input class="nine wide column" type="text" name="student_id" value="{{ member.student_id }}"> <input class="nine wide column" type="text" name="student_id" value="{{ member.student_id }}">
</div> </div>
<div class="ui required inline grid field"> <div class="ui disabled inline grid field">
<label class="three wide column">Student email</label> <label class="three wide column">Student email</label>
<div class="nine wide column">{{ member.email }}</div> <div class="nine wide column">{{ member.email }}</div>
</div> </div>
@ -71,10 +71,40 @@
</select> </select>
</div> </div>
<div class="ui divider"></div> <div class="ui divider"></div>
<div class="ui required inline grid field"> <div class="ui disabled inline grid field">
<label class="three wide column">Membership expiry</label> <label class="three wide column">Membership expiry</label>
<div class="nine wide column">{{ member.expires.strftime('%d %B %Y') }}</div> <div class="nine wide column">{{ member.expires.strftime('%d %B %Y') }}</div>
</div> </div>
{% if 'sspromotions' in settings.INSTALLED_APPS %}
<div class="ui divider"></div>
<h2>Bulletin subscriptions</h2>
<div class="ui required inline grid field">
<label class="three wide column">Opt-in/out</label>
<select id="drop_bulletin_subscribe" class="ui dropdown eleven wide column" name="bulletin_subscribe">
<option value="">Bulletin opt-in/out</option>
<option value="0">Do not email me the MUMUS Bulletin</option>
<option value="1">Email me the weekly MUMUS Bulletin</option>
</select>
</div>
<div class="ui inline grid field">
<label class="three wide column">Subscriptions</label>
<div class="eleven wide column">
{% for group in import('sspromotions.models').Group.objects.all() %}
{% if group.contains_member(member) or group.subscribable %}
<div class="{% if not group.subscribable %}disabled {% endif %}field" style="display: inline; margin-right: 1em;">
<div class="ui checkbox">
<input type="checkbox" name="bulletin_group_{{ group.id }}" id="bulletin_group_{{ group.id }}"{% if group.contains_member(member) %} checked{% endif %}>
<label for="bulletin_group_{{ group.id }}">{{ group.name }}</label>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="ui divider"></div> <div class="ui divider"></div>
{% if errors %} {% if errors %}
<div class="ui visible error message"><ul> <div class="ui visible error message"><ul>
@ -96,6 +126,9 @@
$('.ui.dropdown').dropdown(); $('.ui.dropdown').dropdown();
$('#drop_year').dropdown('set selected', '{{ member.year }}'); $('#drop_year').dropdown('set selected', '{{ member.year }}');
$('#drop_msa').dropdown('set selected', '{{ '1' if member.is_msa else '0' }}'); $('#drop_msa').dropdown('set selected', '{{ '1' if member.is_msa else '0' }}');
{% if 'sspromotions' in settings.INSTALLED_APPS %}
$('#drop_bulletin_subscribe').dropdown('set selected', '{{ '1' if import('sspromotions.models').BulletinSubscription.is_member_subscribed(member) else '0' }}');
{% endif %}
</script> </script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -52,6 +52,15 @@ def index(request):
}) })
member.save() member.save()
return render(request, 'ssmembership/index.html', {'member': member, 'years': models.Member.YEARS})
return render(request, 'ssmembership/index.html', {'member': member}) # Update bulletin
if 'sspromotions' in settings.INSTALLED_APPS:
import sspromotions.models
sspromotions.models.BulletinSubscription.set_member_subscribed(member, True if request.POST['bulletin_subscribe'] == '1' else False)
for group in sspromotions.models.Group.objects.filter(subscribable=True).all():
if ('bulletin_group_' + str(group.id)) in request.POST and request.POST['bulletin_group_' + str(group.id)]:
group.subscribe_member(member, True)
else:
group.subscribe_member(member, False)
return render(request, 'ssmembership/index.html', {'member': member, 'years': models.Member.YEARS})

View File

@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
from ssmembership.models import Member
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
@ -27,6 +29,9 @@ class Group(models.Model):
managers = JSONField(default=[], blank=True) managers = JSONField(default=[], blank=True)
class Meta:
ordering = ['order', 'id']
def __str__(self): def __str__(self):
return self.name return self.name
@ -41,8 +46,40 @@ class Group(models.Model):
return True return True
return False return False
class Meta: def contains_member(self, member):
ordering = ['order', 'id'] if self.subscribable:
return GroupSubscription.objects.filter(member=member, group=self).count() > 0
if self.name == 'All Years':
return True
if next(v for k, v in Member.YEARS if k == member.year) in self.name.split('/'):
# Year level group
return True
return False
def subscribe_member(self, member, subscribe):
if not self.subscribable:
raise Exception('Cannot subscribe to an unsubscribable group')
if subscribe:
if GroupSubscription.objects.filter(member=member, group=self).count() == 0:
subscription = GroupSubscription(member=member, group=self)
subscription.save()
else:
GroupSubscription.objects.filter(member=member, group=self).delete()
@staticmethod
def get_member_groups(member):
# Subscribable groups
subscriptions = GroupSubscription.objects.filter(member=member)
groups = set(subscription.group for subscription in subscriptions.all())
# Non-subscribable groups
for group in Group.objects.filter(subscribable=False):
if group.contains_member(member):
groups.add(group)
return groups
class BulletinItem(models.Model): class BulletinItem(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE) author = models.ForeignKey(User, on_delete=models.CASCADE)
@ -62,3 +99,24 @@ class BulletinItem(models.Model):
if user.email in self.author.delegates: if user.email in self.author.delegates:
return True return True
return False return False
class BulletinSubscription(models.Model):
member = models.ForeignKey(Member, on_delete=models.CASCADE)
subscribed = models.BooleanField()
@staticmethod
def is_member_subscribed(member):
return BulletinSubscription.objects.filter(member=member, subscribed=True).count() > 0
@staticmethod
def set_member_subscribed(member, subscribed):
if BulletinSubscription.objects.filter(member=member).count() > 0:
subscription = BulletinSubscription.objects.get(member=member)
else:
subscription = BulletinSubscription(member=member)
subscription.subscribed = subscribed
subscription.save()
class GroupSubscription(models.Model):
member = models.ForeignKey(Member, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)