Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions intranet/apps/eighth/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class EighthBlockAdmin(SimpleHistoryAdmin):

@admin.register(EighthScheduledActivity)
class EighthScheduledActivityAdmin(SimpleHistoryAdmin):
list_display = ("activity", "block", "comments", "admin_comments", "cancelled", "attendance_taken")
list_filter = ("attendance_taken", "cancelled", "block")
ordering = ("-block", "activity__name")
list_display = ("activity", "block", "hidden_until", "comments", "admin_comments", "cancelled", "attendance_taken")
list_filter = ("attendance_taken", "cancelled", "block", "hidden_until")
ordering = ("-block", "hidden_until", "activity__name")
search_fields = ("activity__name",)


Expand Down
1 change: 1 addition & 0 deletions intranet/apps/eighth/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class SignupException(Exception):
"You may not sign up for this restricted activity. You are not on the authorized list.", "This activity is restricted for this student."
),
"Blacklisted": m("You are blacklisted from this activity.", "This student is blacklisted from this activity."),
"ActivityHidden": m("This activity is currently hidden and cannot be signed up for.", "This activity is currently hidden."),
"OverrideBlockLocked": m(
"An override block ({0}) has been locked. Signup is not allowed at this time.", "An override block ({1}) has been locked."
),
Expand Down
2 changes: 2 additions & 0 deletions intranet/apps/eighth/forms/admin/scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Meta:
"restricted",
"sticky",
"both_blocks",
"hidden_until",
"comments",
"admin_comments",
]
Expand All @@ -57,6 +58,7 @@ class Meta:
"title": forms.TextInput(attrs={"size": 30}),
"comments": forms.Textarea(attrs={"rows": 2, "cols": 30}),
"admin_comments": forms.Textarea(attrs={"rows": 2, "cols": 30}),
"hidden_until": forms.DateTimeInput(attrs={"class": "datetimepicker"}),
}

def clean(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 5.2.8 on 2025-12-23 15:32

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("eighth", "0072_alter_eighthscheduledactivity_waitlist"),
]

operations = [
migrations.AddField(
model_name="eighthscheduledactivity",
name="hidden_until",
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name="historicaleighthscheduledactivity",
name="hidden_until",
field=models.DateTimeField(blank=True, null=True),
),
]
25 changes: 24 additions & 1 deletion intranet/apps/eighth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,14 @@ def get_active_schedulings(self) -> QuerySet | Collection["EighthScheduledActivi

return EighthScheduledActivity.objects.filter(activity=self, block__date__gte=date_start, block__date__lte=date_end)

@property
def is_hidden(self) -> bool:
"""Returns whether the activity is hidden.
Returns:
Whether the activity is hidden.
"""
return self.get_active_schedulings().filter(hidden_until__isnull=False, hidden_until__gt=timezone.now()).exists()

@property
def is_active(self) -> bool:
"""Returns whether an activity is "active."
Expand Down Expand Up @@ -891,7 +899,8 @@ def title_with_flags(self) -> str:
The full title for the scheduled activity, with flags.
"""
cancelled_str = " (Cancelled)" if self.cancelled else ""
name_with_flags = self.activity._name_with_flags(True, self.title) + cancelled_str # pylint: disable=protected-access
hidden_str = " (Hidden)" if self.is_hidden else ""
name_with_flags = self.activity._name_with_flags(True, self.title) + cancelled_str + hidden_str # pylint: disable=protected-access
if self.special and not self.activity.special:
name_with_flags = "Special: " + name_with_flags
return name_with_flags
Expand All @@ -914,6 +923,14 @@ def is_activity_sticky(self) -> bool:
"""
return self.sticky or self.activity.sticky

@property
def is_hidden(self) -> bool:
"""Returns whether the scheduled activity is hidden.
Returns:
Whether this scheduled activity is hidden.
"""
return self.hidden_until is not None and timezone.now() < self.hidden_until

def get_true_sponsors(self) -> QuerySet | Collection[EighthSponsor]: # pylint: disable=unsubscriptable-object
"""Retrieves the sponsors for the scheduled activity, taking into account activity defaults and
overrides.
Expand Down Expand Up @@ -1222,6 +1239,10 @@ def add_user(

exception = eighth_exceptions.SignupException()

if self.is_hidden:
if request is None or not request.user.is_eighth_admin:
exception.ActivityHidden = True

if user.grade and user.grade.number > 12:
exception.SignupForbidden = True

Expand Down Expand Up @@ -1637,6 +1658,8 @@ def __str__(self):
suff = f" - {self.title}" if self.title else ""
return f"{self.activity}{suff} on {self.block}{cancelled_str}"

hidden_until = models.DateTimeField(null=True, blank=True)


class EighthSignupManager(Manager):
"""Model manager for EighthSignup."""
Expand Down
6 changes: 6 additions & 0 deletions intranet/apps/eighth/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Count
from django.utils import timezone
from rest_framework import serializers
from rest_framework.reverse import reverse

Expand Down Expand Up @@ -151,6 +152,8 @@ def process_scheduled_activity(
"sponsors": [],
"restricted": scheduled_activity.get_restricted(),
"restricted_for_user": restricted_for_user,
"hidden": scheduled_activity.is_hidden,
"hidden_until": scheduled_activity.hidden_until,
"both_blocks": scheduled_activity.is_both_blocks(),
"one_a_day": activity.one_a_day,
"special": scheduled_activity.get_special(),
Expand Down Expand Up @@ -231,6 +234,9 @@ def fetch_activity_list_with_metadata(self, block):
.order_by("activity__administrative", "administrative", "activity__name")
)

if user is None or not user.is_eighth_admin:
scheduled_activities = scheduled_activities.exclude(hidden_until__isnull=False, hidden_until__gt=timezone.now())

for scheduled_activity in scheduled_activities:
# Avoid re-fetching scheduled_activity.
activity_info = self.get_activity(
Expand Down
5 changes: 4 additions & 1 deletion intranet/apps/eighth/views/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.db.models import Count
from django.db.models import Count, Q
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, render
from django.utils import timezone
Expand All @@ -35,6 +35,9 @@ def activity_view(request, activity_id=None):
activity = get_object_or_404(EighthActivity, id=activity_id)
scheduled_activities = EighthScheduledActivity.objects.filter(activity=activity)

if request.user.is_student and activity.is_hidden:
scheduled_activities = scheduled_activities.filter(Q(hidden_until__isnull=True) | Q(hidden_until__lte=timezone.now()))

show_all = "show_all" in request.GET
if not show_all:
first_date = timezone.localtime(timezone.now()).date()
Expand Down
2 changes: 2 additions & 0 deletions intranet/apps/eighth/views/admin/scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def schedule_activity_view(request):
"both_blocks",
"comments",
"admin_comments",
"hidden_until",
]
if "rooms" in form.cleaned_data:
for o in form.cleaned_data["rooms"]:
Expand Down Expand Up @@ -234,6 +235,7 @@ def schedule_activity_view(request):
"scheduled": not sched_act.cancelled,
"cancelled": sched_act.cancelled,
"sticky_students": sched_act.sticky_students.all(),
"hidden_until": sched_act.hidden_until,
}
)
except KeyError:
Expand Down
18 changes: 17 additions & 1 deletion intranet/templates/eighth/admin/schedule_activity.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<script src="{% static 'js/vendor/underscore-min.js' %}"></script>
<script src="{% static 'js/vendor/jquery.stickytableheaders.min.js' %}"></script>
<script src="{% static 'js/vendor/jquery.are-you-sure.js' %}"></script>
<script src="{% static 'vendor/datetimepicker-2.4.5/jquery.datetimepicker.js' %}"></script>
<script>
window.all_sponsors = _.values($.parseJSON("{{ sponsors_json }}"));
window.all_rooms_lookup = $.parseJSON("{{ rooms_json }}");
Expand Down Expand Up @@ -79,10 +80,18 @@
</script>

<script src="{% static 'js/eighth/schedule.js' %}"></script>
<script>
$(document).ready(function() {
$(".datetimepicker").datetimepicker({
format: 'Y-m-d H:i:s'
});
});
</script>
{% endblock %}

{% block css %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'vendor/datetimepicker-2.4.5/jquery.datetimepicker.css' %}">
{% stylesheet 'eighth.schedule' %}
{% endblock %}

Expand Down Expand Up @@ -230,6 +239,9 @@ <h4>Select an Activity:</h4>
<th class="both_blocks" colspan="2">
<span>A &amp; B</span>
</th>
<th class="hidden-until" colspan="2">
<span>Hidden Until</span>
</th>
<th>Comments</th><th></th>
<th>Admin Comments</th><th></th>
<th>Sticky Students</th><th></th>
Expand Down Expand Up @@ -307,12 +319,16 @@ <h4>Select an Activity:</h4>
</div>
{% elif field.name == "scheduled" %}
{% render_field field class='scheduled' %}
{% elif field.name == "hidden_until" %}
<div style="text-align: center">
{% render_field field class='datetimepicker' autocomplete='off' %}
</div>
{% else %}
{{ field }}
{% endif %}
</td>

{% if field.name in "rooms capacity sponsors title special administrative restricted sticky both_blocks comments admin_comments sticky_students " %}
{% if field.name in "rooms capacity sponsors title special administrative restricted sticky both_blocks comments admin_comments sticky_students hidden_until" %}
<td class="propagate" data-base-field="{{ field.name }}">
<a class="propagate {{ field.name }} button" title="Propagate" data-block="{{ form.block.value }}" data-field="{{ field.name }}" data-input="{{ field.id_for_label }}">
<i class="fas fa-arrows-alt-v"></i>
Expand Down
10 changes: 10 additions & 0 deletions intranet/templates/eighth/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
<span class="activity-icon fav <% if (favorited) { %>fav-sel<% } %>"></span>
<% if (cancelled) { %>
<span class="activity-icon cancelled"></span>
<% } else if (hidden) { %>
<span class="activity-icon hidden"></span>
<% } else if (restricted_for_user) { %>
<span class="activity-icon restricted"></span>
<% } else if (waitlisted) { %>
Expand Down Expand Up @@ -145,6 +147,10 @@
<span class="badge darkred" title="This activity was cancelled.">CANCELLED</span>
<% } %>

<% if (hidden) { %>
<span class="badge grey" title="This activity is hidden until <%= new Date(hidden_until).toLocaleString('en-US', { month: 'numeric', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }) %>">Hidden</span>
<% } %>

<% if (restricted_for_user) { %>
<span class="badge purple" title="You are not on the authorized list for this restricted activity.">Restricted</span>
<% } else if (restricted) { %>
Expand Down Expand Up @@ -197,6 +203,10 @@ <h3 class="activity-detail-header">
<span class="badge darkred clickable cancelled-badge" data-append-search="is:c" title="This activity was cancelled.">CANCELLED</span>
<% } %>

<% if (hidden) { %>
<span class="badge grey" title="This activity is hidden until <%= new Date(hidden_until).toLocaleString('en-US', { month: 'numeric', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }) %>">Hidden</span>
<% } %>

<% if (special) { %>
<span class="badge green clickable" data-append-search="is:sp" title="This is a special activity.">Special</span>
<% } %>
Expand Down