-
Notifications
You must be signed in to change notification settings - Fork 926
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Trigger an email to admins each time a translation lands back in in t…
…he CMS (#15594) This will probably be a little spammy to start with - emailing each admin once per locale per page/snippet translated, but we will improve this with something custom on the dashboard soon
- Loading branch information
1 parent
811948f
commit aa1e969
Showing
4 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
import logging | ||
from typing import TYPE_CHECKING, Type | ||
|
||
from django.conf import settings | ||
from django.contrib.auth import get_user_model | ||
from django.core.mail import send_mail | ||
from django.template.loader import render_to_string | ||
|
||
from wagtail_localize_smartling.signals import translation_imported | ||
|
||
if TYPE_CHECKING: | ||
from wagtail_localize.models import Translation | ||
from wagtail_localize_smartling.models import Job | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def notify_of_imported_translation( | ||
sender: Type["Job"], | ||
instance: "Job", | ||
translation: "Translation", | ||
**kwargs, | ||
): | ||
""" | ||
Signal handler for receiving news that a translation has landed from | ||
Smartling. | ||
For now, sends a notification email to all Admins | ||
""" | ||
UserModel = get_user_model() | ||
|
||
admin_emails = UserModel.objects.filter( | ||
is_superuser=True, | ||
is_active=True, | ||
).values_list("email", flat=True) | ||
admin_emails = [email for email in admin_emails if email] # Safety check to ensure no empty email addresses are included | ||
|
||
if not admin_emails: | ||
logger.warning("Unable to send translation-imported email alerts: no admins in system") | ||
return | ||
|
||
email_subject = "New translations imported into Bedrock CMS" | ||
|
||
job_name = instance.name | ||
translation_source_name = str(instance.translation_source.get_source_instance()) | ||
|
||
smartling_cms_dashboard_url = f"{settings.WAGTAILADMIN_BASE_URL}/cms-admin/smartling-jobs/inspect/{instance.pk}/" | ||
|
||
email_body = render_to_string( | ||
template_name="cms/email/notifications/translation_imported__body.txt", | ||
context={ | ||
"job_name": job_name, | ||
"translation_source_name": translation_source_name, | ||
"translation_target_language_code": translation.target_locale.language_code, | ||
"smartling_cms_dashboard_url": smartling_cms_dashboard_url, | ||
}, | ||
) | ||
|
||
send_mail( | ||
subject=email_subject, | ||
message=email_body, | ||
from_email=settings.DEFAULT_FROM_EMAIL, | ||
recipient_list=admin_emails, | ||
) | ||
logger.info(f"Translation-imported notification sent to {len(admin_emails)} admins") | ||
|
||
|
||
translation_imported.connect(notify_of_imported_translation, weak=False) |
19 changes: 19 additions & 0 deletions
19
bedrock/cms/templates/cms/email/notifications/translation_imported__body.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Hi there | ||
|
||
ACTION REQUIRED: A new translation has been synced back from Smartling | ||
and needs to be published. | ||
|
||
It is Job '{{job_name}}' for '{{translation_source_name}}' into {{translation_target_language_code}}. | ||
|
||
You can view the job at {{smartling_cms_dashboard_url}} | ||
|
||
From there, for each item listed under "Translations", please open it in a new tab, review and publish it. | ||
|
||
Please note that you may need to publish things in a particular order (e.g. Snippet before the Page that uses it; ) | ||
|
||
Many thanks | ||
|
||
Bedrock-bot | ||
|
||
|
||
P.S. If you find this process painful, please come and tell us about it in #www! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
import logging | ||
|
||
from django.test import override_settings | ||
|
||
import pytest | ||
from wagtail_localize.models import Translation | ||
from wagtail_localize_smartling.models import Job | ||
from wagtail_localize_smartling.signals import translation_imported | ||
|
||
from bedrock.cms.signal_handlers import notify_of_imported_translation | ||
from bedrock.cms.tests.factories import WagtailUserFactory | ||
|
||
pytestmark = [pytest.mark.django_db] | ||
|
||
|
||
def test_translation_imported_is_connected_to_the_expected_handler(): | ||
assert len(translation_imported.receivers) == 1 | ||
assert translation_imported.receivers[0][1] == notify_of_imported_translation | ||
|
||
|
||
@override_settings( | ||
DEFAULT_FROM_EMAIL="from@example.com", | ||
WAGTAILADMIN_BASE_URL="https://cms.example.com", | ||
) | ||
def test_notify_of_imported_translation__happy_path(mocker, caplog): | ||
caplog.set_level(logging.INFO) | ||
|
||
WagtailUserFactory( | ||
username="admin_1", | ||
email="admin_1@example.com", | ||
is_superuser=True, | ||
) | ||
WagtailUserFactory( | ||
username="user_1", | ||
email="user_1@example.com", | ||
is_superuser=False, | ||
) | ||
WagtailUserFactory( | ||
username="admin_2", | ||
email="admin_2@example.com", | ||
is_superuser=True, | ||
) | ||
|
||
mock_job = mocker.MagicMock(spec=Job) | ||
mock_job.name = "Test Job" | ||
mock_job.pk = 9876 | ||
mock_source = mocker.Mock(name="test-source") | ||
mock_job.translation_source.get_source_instance.return_value = mock_source | ||
|
||
mock_translation = mocker.MagicMock(spec=Translation, name="mock-translation") | ||
mock_translation.target_locale.language_code = "fr-CA" | ||
|
||
mock_send_mail = mocker.patch("bedrock.cms.signal_handlers.send_mail") | ||
|
||
translation_imported.send( | ||
sender=Job, | ||
instance=mock_job, | ||
translation=mock_translation, | ||
) | ||
assert mock_send_mail.call_count == 1 | ||
assert mock_send_mail.call_args[1]["subject"] == "New translations imported into Bedrock CMS" | ||
assert mock_send_mail.call_args[1]["from_email"] == "from@example.com" | ||
assert mock_send_mail.call_args[1]["recipient_list"] == ["admin_1@example.com", "admin_2@example.com"] | ||
|
||
for expected_string in [ | ||
"ACTION REQUIRED: A new translation has been synced back from Smartling", | ||
"It is Job 'Test Job'", | ||
"https://cms.example.com/cms-admin/smartling-jobs/inspect/9876/", | ||
]: | ||
assert expected_string in mock_send_mail.call_args[1]["message"] | ||
assert caplog.records[0].message == "Translation-imported notification sent to 2 admins" | ||
|
||
|
||
def test_notify_of_imported_translation__no_admins_in_system(mocker, caplog): | ||
caplog.set_level(logging.INFO) | ||
|
||
mock_job = mocker.MagicMock(spec=Job) | ||
mock_job.name = "Test Job" | ||
mock_job.pk = 9876 | ||
mock_source = mocker.Mock(name="test-source") | ||
mock_job.translation_source.get_source_instance.return_value = mock_source | ||
|
||
mock_translation = mocker.MagicMock(spec=Translation, name="mock-translation") | ||
mock_translation.target_locale.language_code = "fr-CA" | ||
|
||
mock_send_mail = mocker.patch("bedrock.cms.signal_handlers.send_mail") | ||
|
||
translation_imported.send( | ||
sender=Job, | ||
instance=mock_job, | ||
translation=mock_translation, | ||
) | ||
assert mock_send_mail.call_count == 0 | ||
assert caplog.records[0].message == "Unable to send translation-imported email alerts: no admins in system" |