Skip to content

Commit

Permalink
Add subject & body to Email link chooser
Browse files Browse the repository at this point in the history
Closes #5950
Rework of PR #6451
  • Loading branch information
TopDevPros authored and lb- committed Sep 26, 2023
1 parent 3a5cc8e commit 14cd8f0
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Changelog
* Allow subclasses of `PagesAPIViewSet` override default Page model via the `model` attribute (Neeraj Yetheendran, Herbert Poul)
* Allow `ModelViewSet` to be used with models that have non-integer primary keys (Sage Abdullah)
* Add the ability to set an external link/text for promoted search result entries (TopDevPros, Brad Busenius)
* Add support for subject and body in the Email link chooser form (TopDevPros, Alexandre Joly)
* Fix: Ensure that StreamField's `FieldBlock`s correctly set the `required` and `aria-describedby` attributes (Storm Heg)
* Fix: Avoid an error when the moderation panel (admin dashboard) contains both snippets and private pages (Matt Westcott)
* Fix: When deleting collections, ensure the collection name is correctly shown in the success message (LB (Ben) Johnston)
Expand Down
1 change: 1 addition & 0 deletions docs/releases/5.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ depth: 1
* Allow subclasses of `PagesAPIViewSet` override default Page model via the `model` attribute (Neeraj Yetheendran, Herbert Poul)
* Allow `ModelViewSet` to be used with models that have non-integer primary keys (Sage Abdullah)
* Add the ability to set an external link/text for promoted search result entries (TopDevPros, Brad Busenius)
* Add support for subject and body in the Email link chooser form (TopDevPros, Alexandre Joly)

### Bug fixes

Expand Down
2 changes: 2 additions & 0 deletions wagtail/admin/forms/choosers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class AnchorLinkChooserForm(forms.Form):
class EmailLinkChooserForm(forms.Form):
email_address = forms.EmailField(required=True)
link_text = forms.CharField(required=False)
subject = forms.CharField(required=False)
body = forms.CharField(required=False, widget=forms.Textarea(attrs={"rows": 3}))


class PhoneLinkChooserForm(forms.Form):
Expand Down
74 changes: 74 additions & 0 deletions wagtail/admin/tests/test_page_chooser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import urllib.parse as urlparse

from django.contrib.auth import get_user_model
from django.test import TestCase, TransactionTestCase, override_settings
Expand Down Expand Up @@ -869,6 +870,79 @@ def test_create_link(self):
) # When link text is given, it is used
self.assertIs(result["prefer_this_title_as_link_text"], True)

def test_create_link_with_subject_and_body(self):
response = self.post(
{
"email-link-chooser-email_address": "example@example.com",
"email-link-chooser-link_text": "contact",
"email-link-chooser-subject": "Awesome Subject",
"email-link-chooser-body": "An example body",
}
)
self.assertEqual(response.status_code, 200)
result = json.loads(response.content.decode())["result"]
url = result["url"]
self.assertEqual(
url,
"mailto:example@example.com?subject=Awesome%20Subject&body=An%20example%20body",
)
self.assertEqual(
result["title"], "contact"
) # When link text is given, it is used
self.assertIs(result["prefer_this_title_as_link_text"], True)

mail_parts = urlparse.urlparse(url)
query = urlparse.parse_qs(mail_parts.query)
self.assertEqual(mail_parts.path, "example@example.com")
self.assertEqual(query["subject"][0], "Awesome Subject")
self.assertEqual(query["body"][0], "An example body")

def test_create_link_with_subject_only(self):
response = self.post(
{
"email-link-chooser-email_address": "example@example.com",
"email-link-chooser-link_text": "contact",
"email-link-chooser-subject": "Awesome Subject",
}
)
self.assertEqual(response.status_code, 200)
result = json.loads(response.content.decode())["result"]
url = result["url"]
self.assertEqual(url, "mailto:example@example.com?subject=Awesome%20Subject")
self.assertEqual(
result["title"], "contact"
) # When link text is given, it is used
self.assertIs(result["prefer_this_title_as_link_text"], True)

mail_parts = urlparse.urlparse(url)
query = urlparse.parse_qs(mail_parts.query)
self.assertEqual(mail_parts.path, "example@example.com")
self.assertEqual(query["subject"][0], "Awesome Subject")
self.assertTrue("body" not in query)

def test_create_link_with_body_only(self):
response = self.post(
{
"email-link-chooser-email_address": "example@example.com",
"email-link-chooser-link_text": "contact",
"email-link-chooser-body": "An example body",
}
)
self.assertEqual(response.status_code, 200)
result = json.loads(response.content.decode())["result"]
url = result["url"]
self.assertEqual(url, "mailto:example@example.com?body=An%20example%20body")
self.assertEqual(
result["title"], "contact"
) # When link text is given, it is used
self.assertIs(result["prefer_this_title_as_link_text"], True)

mail_parts = urlparse.urlparse(url)
query = urlparse.parse_qs(mail_parts.query)
self.assertEqual(mail_parts.path, "example@example.com")
self.assertEqual(query["body"][0], "An example body")
self.assertTrue("subject" not in query)

def test_create_link_without_text(self):
response = self.post(
{"email-link-chooser-email_address": "example@example.com"}
Expand Down
58 changes: 58 additions & 0 deletions wagtail/admin/views/chooser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import urllib.parse as urlparse

from django.conf import settings
from django.core.paginator import InvalidPage, Paginator
Expand Down Expand Up @@ -734,9 +735,66 @@ class EmailLinkView(BaseLinkFormView):
step_name = "email_link"
link_url_field_name = "email_address"

def get_initial_data(self):
parsed_email = self.parse_email_link(self.request.GET.get("link_url", ""))
return {
"email_address": parsed_email["email"],
"link_text": self.request.GET.get("link_text", ""),
"subject": parsed_email["subject"],
"body": parsed_email["body"],
}

def get_url_from_field_value(self, value):
return "mailto:" + value

def get_result_data(self):
params = {
"subject": self.form.cleaned_data["subject"],
"body": self.form.cleaned_data["body"],
}
encoded_params = urlparse.urlencode(
{k: v for k, v in params.items() if v is not None and v != ""},
quote_via=urlparse.quote,
)

url = "mailto:" + self.form.cleaned_data["email_address"]
if encoded_params:
url += "?" + encoded_params

return {
"url": url,
"title": self.form.cleaned_data["link_text"].strip()
or self.form.cleaned_data["email_address"],
# If the user has explicitly entered / edited something in the link_text field,
# always use that text. If not, we should favour keeping the existing link/selection
# text, where applicable.
"prefer_this_title_as_link_text": ("link_text" in self.form.changed_data),
}

def post(self, request):
self.form = self.form_class(
request.POST, initial=self.get_initial_data(), prefix=self.form_prefix
)

if self.form.is_valid():
result = self.get_result_data()
return self.render_chosen_response(result)
else: # form invalid
return self.render_form_response()

def parse_email_link(self, mailto):
result = {}

mail_result = urlparse.urlparse(mailto)

result["email"] = mail_result.path

query = urlparse.parse_qs(mail_result.query)
result["subject"] = query["subject"][0] if "subject" in query else ""
result["body"] = query["body"][0] if "body" in query else ""

return result


class PhoneLinkView(BaseLinkFormView):
form_prefix = "phone-link-chooser"
Expand Down

0 comments on commit 14cd8f0

Please sign in to comment.