From b04ffe16312c6b669819d228348e7e47c58f4c9b Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 12 Oct 2023 13:07:46 -0400 Subject: [PATCH 1/3] feat: Send mail when slides are approved (#5440) --- .../migrations/0004_slides_approved.py | 27 +++++++++++++++++++ ietf/meeting/tests_views.py | 3 +++ ietf/meeting/views.py | 11 ++++++++ ietf/name/fixtures/names.json | 13 +++++++++ ietf/templates/meeting/slides_approved.txt | 10 +++++++ 5 files changed, 64 insertions(+) create mode 100644 ietf/mailtrigger/migrations/0004_slides_approved.py create mode 100644 ietf/templates/meeting/slides_approved.txt diff --git a/ietf/mailtrigger/migrations/0004_slides_approved.py b/ietf/mailtrigger/migrations/0004_slides_approved.py new file mode 100644 index 000000000..6376e8002 --- /dev/null +++ b/ietf/mailtrigger/migrations/0004_slides_approved.py @@ -0,0 +1,27 @@ +# Copyright The IETF Trust 2023, All Rights Reserved + +from django.db import migrations + +def forward(apps, schema_editor): + MailTrigger = apps.get_model("mailtrigger", "MailTrigger") + Recipient = apps.get_model("mailtrigger", "Recipient") + mt = MailTrigger.objects.create( + slug="slides_approved", + desc="Recipients when slides are approved for a given session", + ) + mt.to.add(Recipient.objects.get(slug="slides_proposer")) + mt.cc.add(Recipient.objects.get(slug="group_chairs")) + +def reverse(apps, schema_editor): + MailTrigger = apps.get_model("mailtrigger", "MailTrigger") + mt = MailTrigger.objects.get(pk="slides_approved") + mt.delete() + +class Migration(migrations.Migration): + dependencies = [ + ("mailtrigger", "0003_ballot_approved_charter"), + ] + + operations = [ + migrations.RunPython(forward, reverse) + ] diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 9609fad3d..01e2c600d 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -6406,6 +6406,9 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) self.assertRegex(r.content.decode(), r"These\s+slides\s+have\s+already\s+been\s+approved") + self.assertEqual(len(outbox), 1) + self.assertIn(submission.submitter.email_address(), outbox[0]['To']) + self.assertIn('Slides approved', outbox[0]['Subject']) def test_approve_proposed_slides_multisession_apply_one(self): submission = SlideSubmissionFactory(session__meeting__type_id='ietf') diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 331f15ad5..5bfdc8b1d 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -4555,6 +4555,17 @@ def approve_proposed_slides(request, slidesubmission_id, num): submission.status = SlideSubmissionStatusName.objects.get(slug='approved') submission.doc = doc submission.save() + (to, cc) = gather_address_lists('slides_approved', group=submission.session.group, proposer=submission.submitter).as_strings() + msg_txt = render_to_string("meeting/slides_approved.txt", { + "to": to, + "cc": cc, + "submission": submission, + "settings": settings, + }) + msg = infer_message(msg_txt) + msg.by = request.user.person + msg.save() + send_mail_message(request, msg) return redirect('ietf.meeting.views.session_details',num=num,acronym=acronym) elif request.POST.get('disapprove'): # Errors in processing a submit request sometimes result diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index e71fe08a7..d105e8c61 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -5588,6 +5588,19 @@ "model": "mailtrigger.mailtrigger", "pk": "session_scheduled" }, + { + "fields": { + "cc": [ + "group_chairs" + ], + "desc": "Recipients when slides are approved for a given session", + "to": [ + "slides_proposer" + ] + }, + "model": "mailtrigger.mailtrigger", + "pk": "slides_approved" + }, { "fields": { "cc": [ diff --git a/ietf/templates/meeting/slides_approved.txt b/ietf/templates/meeting/slides_approved.txt new file mode 100644 index 000000000..efcac88ea --- /dev/null +++ b/ietf/templates/meeting/slides_approved.txt @@ -0,0 +1,10 @@ +{% load ietf_filters %}{% autoescape off %}From: {{settings.DEFAULT_FROM_EMAIL}} +To: {{to}}{% if cc %} +Cc: {{cc}}{% endif %} +Subject: Slides approved for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}{% if session.name %} : {{submission.session.name}}{% endif %} + +Your proposed slides have been approved for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}{% if session.name %} : {{submission.session.name}}{% endif %} + +Title: {{submission.title}} + +{% endautoescape %} \ No newline at end of file From 6f634a049a4784f62c22d76e1892df69cfd9fd9e Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 12 Oct 2023 16:28:26 -0400 Subject: [PATCH 2/3] fix: Don't forget to empty_outbox --- ietf/meeting/tests_views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 01e2c600d..c45caa10e 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -6394,6 +6394,7 @@ class MaterialsTests(TestCase): self.assertIsNone(submission.doc) r = self.client.get(url) self.assertEqual(r.status_code,200) + empty_outbox() r = self.client.post(url,dict(title='different title',approve='approve')) self.assertEqual(r.status_code,302) self.assertEqual(SlideSubmission.objects.filter(status__slug = 'pending').count(), 0) From f6a2d8c5341f521132b07159e9a996e2846c41da Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Fri, 13 Oct 2023 19:22:06 -0400 Subject: [PATCH 3/3] refactor: More efficient mail construction/sending --- ietf/meeting/views.py | 8 +++----- ietf/templates/meeting/slides_approved.txt | 7 +------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 5bfdc8b1d..c23569f0b 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -4556,16 +4556,14 @@ def approve_proposed_slides(request, slidesubmission_id, num): submission.doc = doc submission.save() (to, cc) = gather_address_lists('slides_approved', group=submission.session.group, proposer=submission.submitter).as_strings() - msg_txt = render_to_string("meeting/slides_approved.txt", { + subject = f"Slides approved for {submission.session.meeting} : {submission.session.group.acronym}{' : '+submission.session.name if submission.session.name else ''}" + body = render_to_string("meeting/slides_approved.txt", { "to": to, "cc": cc, "submission": submission, "settings": settings, }) - msg = infer_message(msg_txt) - msg.by = request.user.person - msg.save() - send_mail_message(request, msg) + send_mail_text(request, to, None, subject, body, cc=cc) return redirect('ietf.meeting.views.session_details',num=num,acronym=acronym) elif request.POST.get('disapprove'): # Errors in processing a submit request sometimes result diff --git a/ietf/templates/meeting/slides_approved.txt b/ietf/templates/meeting/slides_approved.txt index efcac88ea..db288ad85 100644 --- a/ietf/templates/meeting/slides_approved.txt +++ b/ietf/templates/meeting/slides_approved.txt @@ -1,9 +1,4 @@ -{% load ietf_filters %}{% autoescape off %}From: {{settings.DEFAULT_FROM_EMAIL}} -To: {{to}}{% if cc %} -Cc: {{cc}}{% endif %} -Subject: Slides approved for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}{% if session.name %} : {{submission.session.name}}{% endif %} - -Your proposed slides have been approved for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}{% if session.name %} : {{submission.session.name}}{% endif %} +{% load ietf_filters %}{% autoescape off %}Your proposed slides have been approved for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}{% if submission.session.name %} : {{submission.session.name}}{% endif %} Title: {{submission.title}}