From 5c2ea6500c6498713e82a2d373faae1dbb2f0a32 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 26 Sep 2025 14:03:36 -0500 Subject: [PATCH 1/9] feat: skeleton for modal email preview --- ietf/doc/tests_draft.py | 16 +++++++ ietf/doc/urls.py | 2 + ietf/doc/views_ballot.py | 18 +++++++- ietf/templates/doc/ballot/edit_position.html | 48 +++++++++++++++++++- 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index ab33acebe6..d853c27b37 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- +import json import os import datetime import io @@ -2391,3 +2392,18 @@ def test_editorial_metadata(self): top_level_metadata_headings = q("tbody>tr>th:first-child").text() self.assertNotIn("IESG", top_level_metadata_headings) self.assertNotIn("IANA", top_level_metadata_headings) + +class BallotEmailAjaxTests(TestCase): + def test_ajax_build_position_email(self): + url = urlreverse("ietf.doc.views_ballot.ajax_build_position_email") + login_testing_unauthorized(self, "secretary", url) + r = self.client.get(url) + self.assertEqual(r.status_code, 405) + r = self.client.post(url, {}) + response = json.loads(r.content) + self.assertFalse(response["success"]) + r = self.client.post(url, {"dict is":"not empty"}) + response = json.loads(r.content) + self.assertTrue(response["success"]) + self.assertIn("email goes here",response["text"]) + diff --git a/ietf/doc/urls.py b/ietf/doc/urls.py index 7b444782d7..51a4064fb8 100644 --- a/ietf/doc/urls.py +++ b/ietf/doc/urls.py @@ -93,6 +93,8 @@ url(r'^ballots/irsg/$', views_ballot.irsg_ballot_status), url(r'^ballots/rsab/$', views_ballot.rsab_ballot_status), + url(r'^build-position-email/$', views_ballot.ajax_build_position_email), + url(r'^(?P(bcp|std|fyi))/?$', views_search.index_subseries), url(r'^%(name)s(?:/%(rev)s)?/$' % settings.URL_REGEXPS, views_doc.document_main), diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index 0ba340890d..b575e11ea1 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -8,7 +8,7 @@ from django import forms from django.conf import settings -from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponseBadRequest +from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseRedirect, Http404, HttpResponseBadRequest from django.shortcuts import render, get_object_or_404, redirect from django.template.defaultfilters import striptags from django.template.loader import render_to_string @@ -300,6 +300,22 @@ def err(code, text): content_type=f"text/plain; charset={settings.DEFAULT_CHARSET}", ) +@role_required("Area Director", "Secretariat") +@csrf_exempt +def ajax_build_position_email(request): + if request.method != "POST": + return HttpResponseNotAllowed(["POST"]) + if not request.POST: + return HttpResponse( + json.dumps({"success": False, "error": "No data submitted"}), + content_type="application/json", + ) + response = { + "success": True, + "text": "rendered email goes here" + } + return HttpResponse(json.dumps(response), content_type="application/json") + def build_position_email(balloter, doc, pos): subj = [] diff --git a/ietf/templates/doc/ballot/edit_position.html b/ietf/templates/doc/ballot/edit_position.html index 293c186112..a60c9eca68 100644 --- a/ietf/templates/doc/ballot/edit_position.html +++ b/ietf/templates/doc/ballot/edit_position.html @@ -33,11 +33,18 @@

{% if field.name == "discuss" %}{% endif %} {% endfor %}
+
Usual actions:
+ - +
+
+
Unusual actions:
+ {% if doc.type_id == "draft" or doc.type_id == "conflrev" %} {% if doc.stream.slug != "irtf" %} {% if ballot_deferred %} @@ -59,6 +66,27 @@

+ + + + + + {% endblock %} {% block js %} + + {% endblock %} \ No newline at end of file From 9c1d50111a94213ac46050fcb80623e243ce061f Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 26 Sep 2025 15:27:48 -0500 Subject: [PATCH 2/9] fix: rudimentary transfer of the comment and discuss text --- ietf/doc/tests_draft.py | 4 +-- ietf/doc/views_ballot.py | 29 ++++++++++++++++---- ietf/templates/doc/ballot/edit_position.html | 28 +++++++++++-------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index d853c27b37..da84c213da 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -2402,8 +2402,8 @@ def test_ajax_build_position_email(self): r = self.client.post(url, {}) response = json.loads(r.content) self.assertFalse(response["success"]) - r = self.client.post(url, {"dict is":"not empty"}) + r = self.client.post(url, {"dictis":"not empty"}) response = json.loads(r.content) self.assertTrue(response["success"]) - self.assertIn("email goes here",response["text"]) + self.assertIn("Discuss:",response["text"]) diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index b575e11ea1..a0f9d14ef9 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -300,19 +300,36 @@ def err(code, text): content_type=f"text/plain; charset={settings.DEFAULT_CHARSET}", ) + @role_required("Area Director", "Secretariat") @csrf_exempt def ajax_build_position_email(request): if request.method != "POST": return HttpResponseNotAllowed(["POST"]) - if not request.POST: - return HttpResponse( - json.dumps({"success": False, "error": "No data submitted"}), - content_type="application/json", - ) + debug.show("request.body") + # if not request.POST: + # return HttpResponse( + # json.dumps({"success": False, "error": "No data submitted"}), + # content_type="application/json", + # ) + # debug.show("request.POST") + # debug.show("form") + # if not form.is_valid(): + # return HttpResponse( + # json.dumps({ + # "success": False, + # "errors": form.errors, + # }) + # ) + # cleaned_data = form.cleaned_data + # discuss = cleaned_data.get("discuss") + # comment = cleaned_data.get("comment") + post_data = json.loads(request.body)["post_data"] + discuss = post_data.get("discuss") + comment = post_data.get("comment") response = { "success": True, - "text": "rendered email goes here" + "text": f"Discuss:\n {discuss}\nComments:\n {comment}" } return HttpResponse(json.dumps(response), content_type="application/json") diff --git a/ietf/templates/doc/ballot/edit_position.html b/ietf/templates/doc/ballot/edit_position.html index a60c9eca68..559603673e 100644 --- a/ietf/templates/doc/ballot/edit_position.html +++ b/ietf/templates/doc/ballot/edit_position.html @@ -65,10 +65,7 @@

Back - - - - + - {% endblock %} {% block js %}