feat(Newsletter): redirect to welcome URL

This commit is contained in:
barredterra 2023-11-24 19:36:24 +01:00
parent e8fe3b2166
commit e5f428ab8b
5 changed files with 197 additions and 78 deletions

View file

@ -1,74 +1,97 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt
frappe.ui.form.on("Email Group", "refresh", function (frm) {
if (!frm.is_new()) {
frm.add_custom_button(
__("Import Subscribers"),
function () {
frappe.prompt(
{
fieldtype: "Select",
options: frm.doc.__onload.import_types,
label: __("Import Email From"),
fieldname: "doctype",
reqd: 1,
},
function (data) {
frappe.call({
method: "frappe.email.doctype.email_group.email_group.import_from",
args: {
name: frm.doc.name,
doctype: data.doctype,
},
callback: function (r) {
frm.set_value("total_subscribers", r.message);
},
});
},
__("Import Subscribers"),
__("Import")
);
},
__("Action")
);
frappe.ui.form.on("Email Group", {
refresh: function (frm) {
if (!frm.is_new()) {
frm.add_custom_button(
__("Import Subscribers"),
function () {
frappe.prompt(
{
fieldtype: "Select",
options: frm.doc.__onload.import_types,
label: __("Import Email From"),
fieldname: "doctype",
reqd: 1,
},
function (data) {
frappe.call({
method: "frappe.email.doctype.email_group.email_group.import_from",
args: {
name: frm.doc.name,
doctype: data.doctype,
},
callback: function (r) {
frm.set_value("total_subscribers", r.message);
},
});
},
__("Import Subscribers"),
__("Import")
);
},
__("Action")
);
frm.add_custom_button(
__("Add Subscribers"),
function () {
frappe.prompt(
{
fieldtype: "Text",
label: __("Email Addresses"),
fieldname: "email_list",
reqd: 1,
},
function (data) {
frappe.call({
method: "frappe.email.doctype.email_group.email_group.add_subscribers",
args: {
name: frm.doc.name,
email_list: data.email_list,
},
callback: function (r) {
frm.set_value("total_subscribers", r.message);
},
});
},
__("Add Subscribers"),
__("Add")
);
},
__("Action")
);
frm.add_custom_button(
__("Add Subscribers"),
function () {
frappe.prompt(
{
fieldtype: "Text",
label: __("Email Addresses"),
fieldname: "email_list",
reqd: 1,
},
function (data) {
frappe.call({
method: "frappe.email.doctype.email_group.email_group.add_subscribers",
args: {
name: frm.doc.name,
email_list: data.email_list,
},
callback: function (r) {
frm.set_value("total_subscribers", r.message);
},
});
},
__("Add Subscribers"),
__("Add")
);
},
__("Action")
);
frm.add_custom_button(
__("New Newsletter"),
function () {
frappe.route_options = { email_group: frm.doc.name };
frappe.new_doc("Newsletter");
},
__("Action")
);
}
frm.add_custom_button(
__("New Newsletter"),
function () {
frappe.route_options = { email_group: frm.doc.name };
frappe.new_doc("Newsletter");
},
__("Action")
);
}
frm.trigger("preview_welcome_url");
},
welcome_url(frm) {
frm.trigger("preview_welcome_url");
},
add_query_parameters: function (frm) {
frm.trigger("preview_welcome_url");
},
preview_welcome_url: function (frm) {
if (frm.doc.add_query_parameters && frm.doc.welcome_url) {
frm.call("preview_welcome_url", { email: "mail@example.org" }).then((r) => {
frm.set_df_property(
"add_query_parameters",
"description",
`${__("Preview:")} ${r.message}`
);
});
} else {
frm.set_df_property("add_query_parameters", "description", "");
}
},
});

View file

@ -9,9 +9,13 @@
"engine": "InnoDB",
"field_order": [
"title",
"column_break_oyyj",
"total_subscribers",
"sign_up_and_confirmation_section",
"confirmation_email_template",
"welcome_email_template"
"welcome_email_template",
"welcome_url",
"add_query_parameters"
],
"fields": [
{
@ -41,6 +45,29 @@
"fieldtype": "Link",
"label": "Welcome Email Template",
"options": "Email Template"
},
{
"fieldname": "column_break_oyyj",
"fieldtype": "Column Break"
},
{
"fieldname": "sign_up_and_confirmation_section",
"fieldtype": "Section Break",
"label": "Sign Up and Confirmation"
},
{
"description": "Redirect to this URL after successful confirmation.",
"fieldname": "welcome_url",
"fieldtype": "Data",
"label": "Welcome URL",
"options": "URL"
},
{
"default": "0",
"depends_on": "welcome_url",
"fieldname": "add_query_parameters",
"fieldtype": "Check",
"label": "Add Query Parameters"
}
],
"index_web_pages_for_search": 1,
@ -51,10 +78,11 @@
"link_fieldname": "email_group"
}
],
"modified": "2021-06-15 11:25:13.556201",
"modified": "2023-11-24 18:35:17.268492",
"modified_by": "Administrator",
"module": "Email",
"name": "Email Group",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
@ -75,5 +103,6 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View file

@ -16,10 +16,12 @@ class EmailGroup(Document):
if TYPE_CHECKING:
from frappe.types import DF
add_query_parameters: DF.Check
confirmation_email_template: DF.Link | None
title: DF.Data
total_subscribers: DF.Int
welcome_email_template: DF.Link | None
welcome_url: DF.Data | None
# end: auto-generated types
def onload(self):
singles = [d.name for d in frappe.get_all("DocType", "name", {"issingle": 1})]
@ -73,6 +75,22 @@ class EmailGroup(Document):
self.name,
)[0][0]
@frappe.whitelist()
def preview_welcome_url(self, email: str | None = None) -> str | None:
"""Get Welcome URL for the email group."""
return self.get_welcome_url(email)
def get_welcome_url(self, email: str | None = None) -> str | None:
"""Get Welcome URL for the email group."""
if not self.welcome_url:
return None
return (
add_query_params(self.welcome_url, {"email": email, "email_group": self.name})
if self.add_query_parameters
else self.welcome_url
)
def on_trash(self):
for d in frappe.get_all("Email Group Member", "name", {"email_group": self.name}):
frappe.delete_doc("Email Group Member", d.name)
@ -125,3 +143,19 @@ def send_welcome_email(welcome_email, email, email_group):
args = dict(email=email, email_group=email_group)
message = frappe.render_template(welcome_email.response_, args)
frappe.sendmail(email, subject=welcome_email.subject, message=message)
def add_query_params(url: str, params: dict) -> str:
from urllib.parse import urlencode, urlparse, urlunparse
if not params:
return url
query_string = urlencode(params)
parsed = list(urlparse(url))
if parsed[4]:
parsed[4] += f"&{query_string}"
else:
parsed[4] = query_string
return urlunparse(parsed)

View file

@ -1,9 +1,32 @@
# Copyright (c) 2015, Frappe Technologies and Contributors
# License: MIT. See LICENSE
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import validate_url
# test_records = frappe.get_test_records('Email Group')
class TestEmailGroup(FrappeTestCase):
pass
def test_welcome_url(self):
email_group = frappe.new_doc("Email Group")
email_group.title = "Test"
email_group.welcome_url = "http://example.com/welcome?hello=world"
email_group.add_query_parameters = 1
email_group.insert()
welcome_url = email_group.get_welcome_url("mail@example.org")
self.assertTrue(validate_url(welcome_url))
self.assertIn(email_group.welcome_url, welcome_url)
self.assertIn("email_group=Test", welcome_url)
self.assertIn("email=mail%40example.org", welcome_url)
email_group.add_query_parameters = 0
welcome_url = email_group.get_welcome_url("mail@example.org")
self.assertTrue(validate_url(welcome_url))
self.assertIn(email_group.welcome_url, welcome_url)
self.assertNotIn("email_group=Test", welcome_url)
self.assertNotIn("email=mail%40example.org", welcome_url)
email_group.welcome_url = ""
self.assertEqual(email_group.get_welcome_url(), None)

View file

@ -365,19 +365,29 @@ def confirm_subscription(email, email_group=None):
if email_group is None:
email_group = get_default_email_group()
if not frappe.db.exists("Email Group", email_group):
frappe.get_doc({"doctype": "Email Group", "title": email_group}).insert(ignore_permissions=True)
try:
group = frappe.get_doc("Email Group", email_group)
except frappe.DoesNotExistError:
group = frappe.get_doc({"doctype": "Email Group", "title": email_group}).insert(
ignore_permissions=True
)
frappe.flags.ignore_permissions = True
add_subscribers(email_group, email)
frappe.db.commit()
frappe.respond_as_web_page(
_("Confirmed"),
_("{0} has been successfully added to the Email Group.").format(email),
indicator_color="green",
)
welcome_url = group.get_welcome_url(email)
if welcome_url:
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = welcome_url
else:
frappe.respond_as_web_page(
_("Confirmed"),
_("{0} has been successfully added to the Email Group.").format(email),
indicator_color="green",
)
def get_list_context(context=None):