Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New club announcements PR (and some other things added in) #1647

Draft
wants to merge 17 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
414935c
feat(announcements): implement models/UI for club announcements
krishnans2006 Feb 11, 2024
0c11a9a
feat(announcements): animate club announcements on dashboard
krishnans2006 Mar 12, 2024
fbcd55f
feat(announcements): filter club announcements by subscription status
krishnans2006 Mar 13, 2024
1562899
refactor: update year on search, announcement request pages
alanzhu0 Mar 29, 2024
af31ec9
refactor(announcements): reword guidelines and remove redundant code
alanzhu0 Mar 29, 2024
19be8e9
perf(announcements): add prefetch query in status view and tighten perms
alanzhu0 Mar 29, 2024
912d348
feat(announcements): continue adding functionality and permissions
alanzhu0 Mar 29, 2024
6dcf06c
style(announcements): dark theme fixes
krishnans2006 Apr 7, 2024
1633b0a
fix(announcements): handle some edge cases
krishnans2006 Apr 7, 2024
8c47d51
style(announcements): improve club announcement form
krishnans2006 Apr 7, 2024
62a9f8a
feat(eighth): add subscribe and unsubscribe buttons everywhere
krishnans2006 Apr 7, 2024
b8d81d8
feat(eighth): add activity settings page for club announcements control
krishnans2006 Apr 8, 2024
0cece59
fix: format and build sources
krishnans2006 Apr 8, 2024
f561323
fix(eighth): fix club announcements settings back button
alanzhu0 Apr 8, 2024
1f6af00
refactor(announcements): text changes
alanzhu0 May 1, 2024
b9dced8
fix: format code, build sources, build docs
krishnans2006 Apr 8, 2024
e2538c5
fix: add club ann. text and remove hoco banner for ann. pages
shrysjain Sep 29, 2024
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
10 changes: 10 additions & 0 deletions Ion.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ intranet/apps/announcements/migrations/0029_alter_warningannouncement_type.py
intranet/apps/announcements/migrations/0030_alter_warningannouncement_type.py
intranet/apps/announcements/migrations/0031_alter_warningannouncement_type.py
intranet/apps/announcements/migrations/0032_alter_warningannouncement_type.py
intranet/apps/announcements/migrations/0033_announcement_activity.py
intranet/apps/announcements/migrations/__init__.py
intranet/apps/api/__init__.py
intranet/apps/api/authentication.py
Expand Down Expand Up @@ -297,6 +298,7 @@ intranet/apps/eighth/tasks.py
intranet/apps/eighth/urls.py
intranet/apps/eighth/utils.py
intranet/apps/eighth/forms/__init__.py
intranet/apps/eighth/forms/activities.py
intranet/apps/eighth/forms/admin/__init__.py
intranet/apps/eighth/forms/admin/activities.py
intranet/apps/eighth/forms/admin/blocks.py
Expand Down Expand Up @@ -385,6 +387,11 @@ intranet/apps/eighth/migrations/0062_auto_20200116_1926.py
intranet/apps/eighth/migrations/0063_auto_20201224_1745.py
intranet/apps/eighth/migrations/0064_auto_20210205_1153.py
intranet/apps/eighth/migrations/0065_auto_20220903_0038.py
intranet/apps/eighth/migrations/0066_eighthactivity_officers.py
intranet/apps/eighth/migrations/0067_eighthactivity_subscribers.py
intranet/apps/eighth/migrations/0068_auto_20240213_1938.py
intranet/apps/eighth/migrations/0069_alter_eighthsponsor_user.py
intranet/apps/eighth/migrations/0070_eighthactivity_club_sponsors.py
intranet/apps/eighth/migrations/__init__.py
intranet/apps/eighth/tests/__init__.py
intranet/apps/eighth/tests/eighth_test.py
Expand Down Expand Up @@ -887,6 +894,7 @@ intranet/static/css/_reset.scss
intranet/static/css/about.scss
intranet/static/css/admin.scss
intranet/static/css/announcements.form.scss
intranet/static/css/announcements.request.scss
intranet/static/css/api.scss
intranet/static/css/base.scss
intranet/static/css/board.scss
Expand Down Expand Up @@ -3271,6 +3279,7 @@ intranet/templates/page_with_nav.html
intranet/templates/announcements/add_modify.html
intranet/templates/announcements/announcement.html
intranet/templates/announcements/approve.html
intranet/templates/announcements/club-request.html
intranet/templates/announcements/delete.html
intranet/templates/announcements/request.html
intranet/templates/announcements/request_status.html
Expand Down Expand Up @@ -3305,6 +3314,7 @@ intranet/templates/docs/privacy.html
intranet/templates/docs/terminology.html
intranet/templates/eighth/absences.html
intranet/templates/eighth/activity.html
intranet/templates/eighth/activity_settings.html
intranet/templates/eighth/edit_profile.html
intranet/templates/eighth/email_students.html
intranet/templates/eighth/empty_state.html
Expand Down
11 changes: 11 additions & 0 deletions docs/sourcedoc/intranet.apps.eighth.forms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ Subpackages

intranet.apps.eighth.forms.admin

Submodules
----------

intranet.apps.eighth.forms.activities module
--------------------------------------------

.. automodule:: intranet.apps.eighth.forms.activities
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

Expand Down
4 changes: 2 additions & 2 deletions intranet/apps/announcements/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@


class AnnouncementAdmin(admin.ModelAdmin):
list_display = ("title", "user", "author", "added")
list_filter = ("added", "updated")
list_display = ("title", "user", "author", "activity", "added")
list_filter = ("added", "updated", "activity")
ordering = ("-added",)
raw_id_fields = ("user",)

Expand Down
64 changes: 43 additions & 21 deletions intranet/apps/announcements/forms.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
import logging

from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model

from ..eighth.models import EighthActivity
from ..users.forms import SortedTeacherMultipleChoiceField
from .models import Announcement, AnnouncementRequest

logger = logging.getLogger(__name__)


class AnnouncementForm(forms.ModelForm):
"""A form for generating an announcement."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["expiration_date"].help_text = "By default, announcements expire after two weeks. To change this, click in the box above."
expiration_date = forms.DateTimeInput()
notify_email_all = forms.BooleanField(required=False, label="Send Email to All")
update_added_date = forms.BooleanField(required=False, label="Update Added Date")

self.fields["notify_post"].help_text = "If this box is checked, students who have signed up for notifications will receive an email."
class Meta:
model = Announcement
fields = ["title", "author", "content", "groups", "expiration_date", "notify_post", "notify_email_all", "update_added_date", "pinned"]
help_texts = {
"expiration_date": "By default, announcements expire after two weeks. To change this, click in the box above.",
"notify_post": "If this box is checked, students who have signed up for notifications will receive an email.",
"notify_email_all": "This will send an email notification to all of the users who can see this post. This option does NOT take users' email notification preferences into account, so please use with care.",
"update_added_date": "If this announcement has already been added, update the added date to now so that the announcement is pushed to the top. If this option is not selected, the announcement will stay in its current position.",
}

self.fields["notify_email_all"].help_text = (
"This will send an email notification to all of the users who can see this post. This option "
"does NOT take users' email notification preferences into account, so please use with care."
)

self.fields["update_added_date"].help_text = (
"If this announcement has already been added, update the added date to now so that the "
"announcement is pushed to the top. If this option is not selected, the announcement will stay in "
"its current position."
)
class ClubAnnouncementForm(forms.ModelForm):
"""A form for posting a club announcement."""

def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)

if user.is_announcements_admin:
self.fields["activity"].queryset = EighthActivity.objects.filter(subscriptions_enabled=True)
elif user.is_club_officer:
self.fields["activity"].queryset = EighthActivity.objects.filter(subscriptions_enabled=True, officers=user)
elif user.is_club_sponsor:
self.fields["activity"].queryset = user.club_sponsor_for_set.filter(subscriptions_enabled=True)
else:
self.fields["activity"].queryset = []
self.fields["activity"].required = True

if "instance" in kwargs: # Don't allow changing the activity once the announcement has been created
self.fields["activity"].widget.attrs["disabled"] = True
self.fields["activity"].required = False

expiration_date = forms.DateTimeInput()
notify_email_all = forms.BooleanField(required=False, label="Send Email to All")
update_added_date = forms.BooleanField(required=False, label="Update Added Date")

class Meta:
model = Announcement
fields = ["title", "author", "content", "groups", "expiration_date", "notify_post", "notify_email_all", "update_added_date", "pinned"]
fields = ["activity", "title", "content", "expiration_date"]
help_texts = {
"expiration_date": "By default, announcements expire after two weeks. To change this, click in the box above.",
}


class AnnouncementEditForm(forms.ModelForm):
Expand Down Expand Up @@ -69,10 +94,7 @@ class AnnouncementRequestForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["title"].help_text = (
"The title of the announcement that will appear on Intranet. Please enter "
"a title more specific than just \"[Club name]'s Intranet Posting'."
)
self.fields["title"].help_text = "The title of the announcement that will appear on Intranet."
self.fields["author"].help_text = (
"If you want this post to have a custom author entry, such as "
'"Basket Weaving Club" or "TJ Faculty," enter that name here. '
Expand All @@ -83,7 +105,7 @@ def __init__(self, *args, **kwargs):
self.fields["notes"].help_text = (
"Any information about this announcement you wish to share with the Intranet "
"administrators and teachers selected above. If you want to restrict this posting "
"to a specific group of students, such as the Class of 2016, enter that request here."
f"to a specific group of students, such as the Class of {settings.SENIOR_GRADUATION_YEAR}, enter that request here."
)
self.fields["teachers_requested"] = SortedTeacherMultipleChoiceField(
queryset=get_user_model().objects.get_approve_announcements_users_sorted(), show_username=True
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 3.2.20 on 2024-02-14 00:06

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('eighth', '0067_eighthactivity_subscribers'),
('announcements', '0032_alter_warningannouncement_type'),
]

operations = [
migrations.AddField(
model_name='announcement',
name='activity',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='eighth.eighthactivity'),
),
]
20 changes: 17 additions & 3 deletions intranet/apps/announcements/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ...utils.date import get_date_range_this_year, is_current_year
from ...utils.deletion import set_historical_user
from ...utils.html import nullify_links
from ..eighth.models import EighthActivity


class AnnouncementManager(Manager):
Expand Down Expand Up @@ -88,7 +89,7 @@ class Announcement(models.Model):
The title of the announcement
content
The HTML content of the news post
authors
author
The name of the author
added
The date the announcement was added
Expand All @@ -110,6 +111,8 @@ class Announcement(models.Model):
updated = models.DateTimeField(auto_now=True)
groups = models.ManyToManyField(DjangoGroup, blank=True)

activity = models.ForeignKey(EighthActivity, null=True, blank=True, on_delete=models.CASCADE)

expiration_date = models.DateTimeField(auto_now=False, default=timezone.make_aware(datetime(3000, 1, 1)))

notify_post = models.BooleanField(default=True)
Expand Down Expand Up @@ -141,9 +144,20 @@ def is_this_year(self):
"""Return whether the announcement was created after July 1st of this school year."""
return is_current_year(self.added)

@property
def is_club_announcement(self):
return self.activity is not None

def is_visible(self, user):
return self in Announcement.objects.visible_to_user(user)

def can_modify(self, user):
return (
user.is_announcements_admin
or self.is_club_announcement
and (self.is_visible_submitter(user) or user.club_sponsor_for_set.filter(id=self.activity.id).exists())
)

# False, not None. This can be None if no AnnouncementRequest exists for this Announcement,
# and we should not reevaluate in that case.
_announcementrequest = False # type: AnnouncementRequest
Expand All @@ -157,13 +171,13 @@ def announcementrequest(self):

def is_visible_requester(self, user):
try:
return self.announcementrequest_set.filter(teachers_requested__id=user.id).exists()
return self.announcementrequest_set.filter(teachers_requested=user).exists()
except get_user_model().DoesNotExist:
return False

def is_visible_submitter(self, user):
try:
return (self.announcementrequest and user.id == self.announcementrequest.user_id) or self.user_id == user.id
return self.user == user or self.announcementrequest and user == self.announcementrequest.user
except get_user_model().DoesNotExist:
return False

Expand Down
8 changes: 8 additions & 0 deletions intranet/apps/announcements/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ def announcement_posted_email(request, obj, send_all=False):
.objects.filter(user_type="student", graduation_year__gte=get_senior_graduation_year())
.union(get_user_model().objects.filter(user_type__in=["teacher", "counselor"]))
)
elif obj.activity:
subject = f"Club Announcement for {obj.activity.name}: {obj.title}"
users = (
get_user_model()
.objects.filter(user_type="student", graduation_year__gte=get_senior_graduation_year(), subscribed_to_set__contains=obj.activity)
.union(get_user_model().objects.filter(user_type__in=["teacher", "counselor"], subscribed_to_set__contains=obj.activity))
)

else:
users = (
get_user_model()
Expand Down
3 changes: 3 additions & 0 deletions intranet/apps/announcements/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
urlpatterns = [
re_path(r"^$", views.view_announcements, name="view_announcements"),
re_path(r"^/archive$", views.view_announcements_archive, name="announcements_archive"),
re_path(r"^/club$", views.view_club_announcements, name="club_announcements"),
re_path(r"^/add$", views.add_announcement_view, name="add_announcement"),
re_path(r"^/request$", views.request_announcement_view, name="request_announcement"),
re_path(r"^/club/add$", views.add_club_announcement_view, name="add_club_announcement"),
re_path(r"^/club/modify/(?P<announcement_id>\d+)$", views.modify_club_announcement_view, name="modify_club_announcement"),
re_path(r"^/request/success$", views.request_announcement_success_view, name="request_announcement_success"),
re_path(r"^/request/success_self$", views.request_announcement_success_self_view, name="request_announcement_success_self"),
re_path(r"^/approve/(?P<req_id>\d+)$", views.approve_announcement_view, name="approve_announcement"),
Expand Down
Loading