Skip to content

Commit 81edff8

Browse files
committed
feat(enrichment): add restricted activity functionality
1 parent d80c923 commit 81edff8

File tree

10 files changed

+167
-52
lines changed

10 files changed

+167
-52
lines changed

Ion.egg-info/PKG-INFO

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Intranet 3
9191
*Version 3.0.0*
9292

9393
Intranet3 (Ion) is the next-generation Intranet platform for `TJHSST
94-
<https://www.tjhsst.edu/>`_. Using Python, Django, Redis, Postgres, and many other technologies, Ion was developed from the ground up to be simple, well-documented, and extensible.
94+
<https://tjhsst.fcps.edu/>`_. Using Python, Django, Redis, Postgres, and many other technologies, Ion was developed from the ground up to be simple, well-documented, and extensible.
9595

9696
Documentation (in RestructuredText format) is available inside the "docs" folder or at https://tjcsl.github.io/ion publicly on the web.
9797

Ion.egg-info/SOURCES.txt

+1
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ intranet/apps/enrichment/urls.py
453453
intranet/apps/enrichment/views.py
454454
intranet/apps/enrichment/migrations/0001_initial.py
455455
intranet/apps/enrichment/migrations/0002_alter_enrichmentactivity_options.py
456+
intranet/apps/enrichment/migrations/0003_auto_20240307_2313.py
456457
intranet/apps/enrichment/migrations/__init__.py
457458
intranet/apps/error/__init__.py
458459
intranet/apps/error/tests.py

intranet/apps/enrichment/forms.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,4 @@ def __init__(self, *args, **kwargs):
1212
class Meta:
1313
model = EnrichmentActivity
1414

15-
fields = [
16-
"title",
17-
"description",
18-
"time",
19-
"location",
20-
"capacity",
21-
"presign",
22-
]
15+
fields = ["title", "description", "time", "location", "capacity", "presign", "groups_allowed", "groups_blacklisted"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 3.2.20 on 2024-03-08 04:13
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('auth', '0012_alter_user_first_name_max_length'),
10+
('enrichment', '0002_alter_enrichmentactivity_options'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='enrichmentactivity',
16+
name='groups_allowed',
17+
field=models.ManyToManyField(blank=True, related_name='allowed_enrichments_set', to='auth.Group'),
18+
),
19+
migrations.AddField(
20+
model_name='enrichmentactivity',
21+
name='groups_blacklisted',
22+
field=models.ManyToManyField(blank=True, related_name='blacklisted_enrichments_set', to='auth.Group'),
23+
),
24+
]

intranet/apps/enrichment/models.py

+24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22

33
from django.conf import settings
4+
from django.contrib.auth.models import Group as DjangoGroup
45
from django.db import models
56
from django.db.models import Manager
67
from django.utils import timezone
@@ -51,6 +52,25 @@ class EnrichmentActivity(models.Model):
5152

5253
presign = models.BooleanField(default=False)
5354

55+
groups_allowed = models.ManyToManyField(DjangoGroup, related_name="allowed_enrichments_set", blank=True)
56+
groups_blacklisted = models.ManyToManyField(DjangoGroup, related_name="blacklisted_enrichments_set", blank=True)
57+
58+
def user_can_signup(self, user):
59+
"""Return whether a user can sign up for an enrichment activity.
60+
61+
Args:
62+
user: The user to check.
63+
64+
Returns:
65+
Whether the user can sign up for the enrichment activity.
66+
"""
67+
return (not self.groups_allowed.exists() or any(group in user.groups.all() for group in self.groups_allowed.all())) and not any(
68+
group in user.groups.all() for group in self.groups_blacklisted.all()
69+
)
70+
71+
def user_is_blacklisted(self, user):
72+
return any(group in user.groups.all() for group in self.groups_blacklisted.all())
73+
5474
@property
5575
def is_this_year(self):
5676
"""Return whether the enrichment activity was created after the start of the school year."""
@@ -61,6 +81,10 @@ def happened(self):
6181
"""Return whether an enrichment activity has happened."""
6282
return self.time < timezone.now()
6383

84+
@property
85+
def restricted(self):
86+
return self.groups_allowed.exists()
87+
6488
@property
6589
def is_too_early_to_signup(self):
6690
"""Returns whether it is too early to sign up for the activity

intranet/apps/enrichment/views.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,12 @@ def enrichment_view(request):
160160
{"title": "This month", "enrichments": viewable_enrichments.filter(time__gte=this_month[0], time__lt=this_month[1])},
161161
]
162162

163+
week_and_month = viewable_enrichments.filter(time__gte=this_week[0], time__lt=this_month[1])
163164
if not show_all and not classic:
164165
enrichments_categories.append(
165166
{
166167
"title": "Week and month",
167-
"enrichments": viewable_enrichments.filter(time__gte=this_week[0], time__lt=this_month[1]),
168+
"enrichments": week_and_month,
168169
}
169170
)
170171

@@ -180,6 +181,8 @@ def enrichment_view(request):
180181

181182
context = {
182183
"enrichments": enrichments_categories,
184+
"authorized_enrichments": {e.id for e in week_and_month if e.user_can_signup(request.user)},
185+
"blacklisted_enrichments": {e.id for e in week_and_month if e.user_is_blacklisted(request.user)},
183186
"num_enrichments": num_enrichments,
184187
"is_enrichment_admin": is_enrichment_admin,
185188
"show_attend": True,
@@ -209,6 +212,10 @@ def enrichment_signup_view(request, enrichment_id):
209212
messages.error(request, "Signups are locked for this enrichment activity.")
210213
return redirect("enrichment")
211214

215+
if not enrichment.user_can_signup(request.user):
216+
messages.error(request, "You do not have permission to sign up for this enrichment activity.")
217+
return redirect("enrichment")
218+
212219
if enrichment.presign:
213220
too_early_to_signup = enrichment.is_too_early_to_signup
214221
if too_early_to_signup[0]:
@@ -249,6 +256,8 @@ def enrichment_roster_view(request, enrichment_id):
249256

250257
context = {
251258
"enrichment": enrichment,
259+
"authorized_enrichments": {enrichment.id if enrichment.user_can_signup(request.user) else None},
260+
"blacklisted_enrichments": {enrichment.id if enrichment.user_is_blacklisted(request.user) else None},
252261
"enrichment_time": enrichment.time.astimezone(timezone.get_default_timezone()),
253262
"enrichment_is_today": enrichment_is_today,
254263
"roster": enrichment.attending.all().order_by("first_name", "last_name"),

intranet/static/css/enrichment.scss

+16
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@
5858
display: none;
5959
}
6060

61+
.selectize-control {
62+
margin-top: 4px;
63+
}
64+
65+
.schedule {
66+
min-height: 65vh;
67+
}
68+
6169

6270
@keyframes gradient {
6371
0% {
@@ -71,6 +79,14 @@
7179
}
7280
}
7381

82+
@media(min-width: 768px) {
83+
.signup-notice {
84+
width: 40vw;
85+
position: relative;
86+
left: 15px;
87+
}
88+
}
89+
7490
@media(max-width: 550px) {
7591
.attending-badge {
7692
display: block;

intranet/templates/enrichment/add_modify.html

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
create: true
2525
})
2626

27+
$("#id_groups_allowed").selectize({
28+
create: false
29+
})
30+
31+
$("#id_groups_blacklisted").selectize({
32+
create: false
33+
});
34+
2735
// name of <textarea> is description
2836
var editor = CKEDITOR.replace("id_description", {
2937
width: "600px"
@@ -46,6 +54,7 @@
4654
<link rel="stylesheet" href="{% static 'vendor/datetimepicker-2.4.5/jquery.datetimepicker.css' %}">
4755
<link rel="stylesheet" href="{% static 'vendor/selectize.js-0.12.4/dist/css/selectize.default.css' %}">
4856
{% stylesheet 'announcements.form' %}
57+
{% stylesheet 'enrichment' %}
4958
{% endblock %}
5059

5160
{% block head %}

intranet/templates/enrichment/enrichment.html

+73-42
Original file line numberDiff line numberDiff line change
@@ -43,67 +43,98 @@ <h3 style="font-size: 15px; margin-top: auto;">
4343
</div>
4444
<div class="enrichment-metadata event-metadata">
4545
{{ enrichment.attending.all|length }}/{{ enrichment.capacity }} signups
46-
47-
{% if enrichment.presign %}
46+
{% if enrichment.presign or enrichment.restricted %}
4847
&bull;
48+
{% endif %}
49+
{% if enrichment.presign %}
4950
<span
5051
class="badge yellow clickable"
51-
data-append-search="is:p"
5252
title="Signups for this enrichment activity open on {{ enrichment.is_too_early_to_signup.1|date:'l, F j' }} at {{ enrichment.is_too_early_to_signup.1|date:'P' }}">
5353
2 day
5454
</span>
5555
{% endif %}
56+
{% if enrichment.restricted %}
57+
{% if enrichment.id in authorized_enrichments %}
58+
<span class="badge green clickable" title="You are authorized to sign up for this restricted activity.">
59+
Authorized
60+
</span>
61+
{% else %}
62+
<span class="badge purple clickable" title="This activity is restricted to those on the authorized list.">
63+
Restricted
64+
</span>
65+
{% endif %}
66+
{% endif %}
5667
</div>
5768
<div class="enrichment-content" style="font-size:14px;">
5869
{{ enrichment.description|safe }}
5970
</div>
6071
</div>
6172
<div class="enrichment enrichment-bottom event {% if request.user in enrichment.attending.all %}signed-up{% endif %}">
6273
{% if not enrichment.happened %}
63-
<form data-form-attend="{{ enrichment.id }}" action="{% url 'enrichment_signup' enrichment.id %}" method="post" style="font-size: 12px">
64-
{% csrf_token %}
65-
{% if request.user in enrichment.attending.all %}
66-
<span {% if enrichment_is_today %} style="color: green" {% endif %}>
67-
<i class="fas fa-check"></i> You are signed up for this activity.
68-
</span>
69-
<br>
70-
<a data-form-attend="{{ enrichment.id }}" class="button small-button no-attend-button attend-button">
71-
<i class="fas fa-times"></i>
72-
Remove Signup
73-
</a>
74-
{% else %}
75-
<input type="hidden" name="attending" value="true">
76-
<a data-form-attend="{{ enrichment.id }}" class="button attend-button">
77-
Sign Up
78-
</a>
79-
{% endif %}
80-
</form>
74+
{% if enrichment.id in blacklisted_enrichments %}
75+
<div class="enrichment-content" style="font-size:12px;">
76+
<i class="fas fa-times" style="color: red"></i>
77+
You have been blocked from signing up for this activity.
78+
Contact the activity sponsor for more information.
79+
</div>
80+
{% elif enrichment.restricted and enrichment.id not in authorized_enrichments %}
81+
<div class="enrichment-content" style="font-size:12px;">
82+
<i class="fas fa-times"></i>
83+
Signups for this activity are restricted to those on the authorized list.
84+
</div>
85+
{% else %}
86+
<form data-form-attend="{{ enrichment.id }}" action="{% url 'enrichment_signup' enrichment.id %}" method="post" style="font-size: 12px">
87+
{% csrf_token %}
88+
{% if request.user in enrichment.attending.all %}
89+
<span {% if enrichment_is_today %} style="color: green" {% endif %}>
90+
<i class="fas fa-check"></i> You are signed up for this activity.
91+
</span>
92+
<br>
93+
<a data-form-attend="{{ enrichment.id }}" class="button small-button no-attend-button attend-button">
94+
<i class="fas fa-times"></i>
95+
Remove Signup
96+
</a>
97+
{% else %}
98+
<input type="hidden" name="attending" value="true">
99+
<a data-form-attend="{{ enrichment.id }}" class="button attend-button">
100+
Sign Up
101+
</a>
102+
{% endif %}
103+
</form>
104+
{% endif %}
81105
{% else %}
82106
<div class="enrichment-content" style="font-size:12px;">
83107
{% if request.user in enrichment.attending.all %}
84-
{% if not enrichment_is_today %}
85-
<i class="fas fa-check"></i>
86-
You signed up for this activity.
87-
108+
{% if enrichment.id in blacklisted_enrichments %}
109+
<div class="enrichment-content" style="font-size:12px;">
110+
<i class="fas fa-times" style="color: red"></i>
111+
You have been blocked from signing up for this activity.
112+
Contact the activity sponsor for more information.
113+
</div>
88114
{% else %}
89-
<span style="color: green">
90-
<i class="fas fa-check"></i>
91-
You are signed up for this activity.
92-
</span>
93-
{% comment %} <br>
94-
<hr>
95-
<span class="remove-signup-text">
96-
You can still remove your signup, but you will not be able to sign up again.
97-
</span>
98-
<br>
115+
{% if not enrichment_is_today %} {# This shouldn't happen, but just in case #}
116+
<i class="fas fa-check"></i>
117+
You signed up for this activity.
118+
{% else %}
119+
<span style="color: green">
120+
<i class="fas fa-check"></i>
121+
You are signed up for this activity.
122+
</span>
123+
{% comment %} <br>
124+
<hr>
125+
<span class="remove-signup-text">
126+
You can still remove your signup, but you will not be able to sign up again.
127+
</span>
128+
<br>
99129

100-
<form data-form-attend="{{ enrichment.id }}" action="{% url 'enrichment_signup' enrichment.id %}" method="post">
101-
{% csrf_token %}
102-
<a data-form-attend="{{ enrichment.id }}" style="margin-top: 3px" class="button small-button no-attend-button attend-button">
103-
<i class="fas fa-times"></i>
104-
Remove Signup
105-
</a>
106-
</form> {% endcomment %}
130+
<form data-form-attend="{{ enrichment.id }}" action="{% url 'enrichment_signup' enrichment.id %}" method="post">
131+
{% csrf_token %}
132+
<a data-form-attend="{{ enrichment.id }}" style="margin-top: 3px" class="button small-button no-attend-button attend-button">
133+
<i class="fas fa-times"></i>
134+
Remove Signup
135+
</a>
136+
</form> {% endcomment %}
137+
{% endif %}
107138
{% endif %}
108139
{% else %}
109140
<i class="fas fa-times"></i>

intranet/templates/enrichment/home.html

+8
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ <h2 class="category">{{ category.title }}:</h2>
143143
<div class="enrichment-container" id="view-div"></div>
144144
{% endif %}
145145

146+
<div class="signup-notice">
147+
<hr>
148+
<i class="fas fa-info-circle"></i> Students should not repeatedly signup for enrichment activities and not
149+
attend, as this takes away spots from other students. Please remove your signup if
150+
you do not plan to attend. Repeat offenders may lose enrichment activity signup
151+
privileges.
152+
<hr>
153+
</div>
146154
</div>
147155
{# This needs to be at the bottom for the content to properly load #}
148156
<script src="{% static 'js/events.js' %}"></script>

0 commit comments

Comments
 (0)