Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor wagtail hooks #424

Merged
merged 4 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions home/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.core.validators import MaxLengthValidator
from django.db import models
from django.forms import CheckboxSelectMultiple
from django.template.defaultfilters import truncatechars
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from modelcluster.contrib.taggit import ClusterTaggableManager
Expand Down Expand Up @@ -499,6 +500,8 @@ class QuickReplyContent(ItemBase):


class ContentPage(UniqueSlugMixin, Page, ContentImportMixin):
body_truncate_size = 200

class WhatsAppTemplateCategory(models.TextChoices):
MARKETING = "MARKETING", _("Marketing")
UTILITY = "UTILITY", _("Utility")
Expand Down Expand Up @@ -973,6 +976,70 @@ def save_revision(
revision.save(update_fields=["content"])
return revision

def short_description(description):
def set_short_description(func):
func.short_description = description
return func

return set_short_description

@short_description("Quick Replies")
def replies(self):
return list(self.quick_replies.all())

@short_description("Triggers")
def trigger(self):
return list(self.triggers.all())

@short_description("Tags")
def tag(self):
return list(self.tags.all())

@short_description("Whatsapp Body")
def wa_body(self):
body = (
"\n".join(m.value["message"] for m in self.whatsapp_body)
if self.whatsapp_body
else ""
)
return truncatechars(str(body), self.body_truncate_size)

@short_description("SMS Body")
def sms_body_message(self):
body = (
"\n".join(m.value["message"] for m in self.sms_body)
if self.sms_body
else ""
)
return truncatechars(str(body), self.body_truncate_size)

@short_description("USSD Body")
def ussd_body_message(self):
body = (
"\n".join(m.value["message"] for m in self.ussd_body)
if self.ussd_body
else ""
)
return truncatechars(str(body), self.body_truncate_size)

@short_description("Messenger Body")
def mess_body(self):
body = "\n".join(m.value["message"] for m in self.messenger_body)
return truncatechars(str(body), self.body_truncate_size)

@short_description("Viber Body")
def vib_body(self):
body = "\n".join(m.value["message"] for m in self.viber_body)
return truncatechars(str(body), self.body_truncate_size)

@short_description("Web Body")
def web_body(self):
return truncatechars(str(self.body), self.body_truncate_size)

@short_description("Parent")
def parental(self):
return self.get_parent()

def clean(self):
result = super().clean(Page)
errors = {}
Expand Down
24 changes: 24 additions & 0 deletions home/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,30 @@ def test_template_create_with_pt_language(self, mock_create_whatsapp_template):
[],
)

def test_body_text_truncation(self):
"""
Body text for web, whatsapp, messenger, and viber, should be truncated in this
list view
"""
page = ContentPage(
body=[("paragraph", "test " * 100)],
)

page.whatsapp_body.append(("Whatsapp_Message", {"message": "test " * 100}))
page.messenger_body.append(("messenger_block", {"message": "test " * 100}))
page.viber_body.append(("viber_message", {"message": "test " * 100}))

self.assertEqual(len(page.web_body()), 200)
self.assertEqual(len(page.wa_body()), 200)
self.assertEqual(len(page.mess_body()), 200)
self.assertEqual(len(page.vib_body()), 200)

# Web body is different to the rest because of the html
self.assertEqual(page.web_body()[-6:], "test …")
self.assertEqual(page.wa_body()[-5:], "test…")
self.assertEqual(page.mess_body()[-5:], "test…")
self.assertEqual(page.vib_body()[-5:], "test…")


class OrderedContentSetTests(TestCase):
def test_get_gender_none(self):
Expand Down
29 changes: 1 addition & 28 deletions home/tests/test_wagtail_hooks.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import pytest
from django.test import TestCase
from wagtail.models import Locale

from home.models import ContentPage, HomePage, OrderedContentSet
from home.wagtail_hooks import ContentPageAdmin
from home.models import HomePage, OrderedContentSet

from .page_builder import PageBtn, PageBuilder, WABlk, WABody

Expand All @@ -17,31 +15,6 @@ def admin_client(client, django_user_model):
return client


class ContentPageAdminTests(TestCase):
def test_body_text_truncation(self):
"""
Body text for web, whatsapp, messenger, and viber, should be truncated in this
list view
"""
page = ContentPage(
body=[("paragraph", "test " * 100)],
)
page.whatsapp_body.append(("Whatsapp_Message", {"message": "test " * 100}))
page.messenger_body.append(("messenger_block", {"message": "test " * 100}))
page.viber_body.append(("viber_message", {"message": "test " * 100}))
admin = ContentPageAdmin()

self.assertEqual(len(admin.web_body(page)), 200)
self.assertEqual(len(admin.wa_body(page)), 200)
self.assertEqual(len(admin.mess_body(page)), 200)
self.assertEqual(len(admin.vib_body(page)), 200)
# Web body is different to the rest because of the html
self.assertEqual(admin.web_body(page)[-6:], "test …")
self.assertEqual(admin.wa_body(page)[-5:], "test…")
self.assertEqual(admin.mess_body(page)[-5:], "test…")
self.assertEqual(admin.vib_body(page)[-5:], "test…")


@pytest.mark.django_db
class TestBeforeDeletePageHook:
def create_content_page(self, title="default page", wa_buttons=None):
Expand Down
102 changes: 29 additions & 73 deletions home/wagtail_hooks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from django.conf import settings
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.template.defaultfilters import truncatechars
from django.urls import path, reverse
from wagtail import hooks
from wagtail.admin import widgets as wagtailadmin_widgets
Expand All @@ -28,7 +27,11 @@


@hooks.register("before_delete_page")
def before_delete_page(request, page):
def prevent_deletion_if_linked(request, page):
"""
Check if the page is a ContentPage and if it has any links to prevent
the deletion of a page if it is linked to other content.
"""
if page.content_type.name != ContentPage._meta.verbose_name:
return
page_links, orderedcontentset_links, wat_links = page.get_all_links()
Expand All @@ -51,7 +54,10 @@ def before_delete_page(request, page):


@hooks.register("register_admin_urls")
def register_import_urls():
def get_import_urls():
"""
Create additional admin URLs for various content import views.
"""
return [
path("import/", ContentUploadView.as_view(), name="import"),
path(
Expand All @@ -73,14 +79,20 @@ def register_import_urls():


@hooks.register("register_page_listing_buttons")
def page_listing_buttons(page, page_perms, is_parent=False, next_url=None):
def get_import_content_button(page, page_perms, is_parent=False, next_url=None):
"""
Generate buttons to add to action list for importing content.
"""
yield wagtailadmin_widgets.PageListingButton(
"Import Content", reverse("import"), priority=10
)


@hooks.register("register_reports_menu_item")
def register_stale_content_report_menu_item():
def get_stale_content_report_menu_item():
"""
Create a admin only sub menu item for the Stale Content report.
"""
return AdminOnlyMenuItem(
"Stale Content",
reverse("stale_content_report"),
Expand All @@ -90,7 +102,10 @@ def register_stale_content_report_menu_item():


@hooks.register("register_admin_urls")
def register_stale_content_report_url():
def get_stale_content_report_url():
"""
Create additional URL for the State Content Report.
"""
return [
path(
"reports/stale-content/",
Expand All @@ -101,7 +116,10 @@ def register_stale_content_report_url():


@hooks.register("register_reports_menu_item")
def register_page_views_report_menu_item():
def get_page_views_report_menu_item():
"""
Create an admin only sub menu item for the Page Views report.
"""
return AdminOnlyMenuItem(
"Page Views",
reverse("page_view_report"),
Expand All @@ -111,7 +129,10 @@ def register_page_views_report_menu_item():


@hooks.register("register_admin_urls")
def register_page_views_report_url():
def get_page_views_report_url():
"""
Create additional URL for the Page Views report.
"""
return [
path(
"reports/page-views/",
Expand Down Expand Up @@ -160,71 +181,6 @@ class ContentPageAdmin(ModelAdmin):
)
list_export = ("locale", "title")

def replies(self, obj):
return list(obj.quick_replies.all())

replies.short_description = "Quick Replies"

def trigger(self, obj):
return list(obj.triggers.all())

trigger.short_description = "Triggers"

def tag(self, obj):
return list(obj.tags.all())

tag.short_description = "Tags"

def wa_body(self, obj):
body = (
"\n".join(m.value["message"] for m in obj.whatsapp_body)
if obj.whatsapp_body
else ""
)
return truncatechars(str(body), self.body_truncate_size)

wa_body.short_description = "Whatsapp Body"

def sms_body(self, obj):
body = (
"\n".join(m.value["message"] for m in obj.sms_body) if obj.sms_body else ""
)
return truncatechars(str(body), self.body_truncate_size)

sms_body.short_description = "SMS Body"

def ussd_body(self, obj):
body = (
"\n".join(m.value["message"] for m in obj.ussd_body)
if obj.ussd_body
else ""
)
return truncatechars(str(body), self.body_truncate_size)

ussd_body.short_description = "USSD Body"

def mess_body(self, obj):
body = "\n".join(m.value["message"] for m in obj.messenger_body)
return truncatechars(str(body), self.body_truncate_size)

mess_body.short_description = "Messenger Body"

def vib_body(self, obj):
body = "\n".join(m.value["message"] for m in obj.viber_body)
return truncatechars(str(body), self.body_truncate_size)

vib_body.short_description = "Viber Body"

def web_body(self, obj):
return truncatechars(str(obj.body), self.body_truncate_size)

web_body.short_description = "Web Body"

def parental(self, obj):
return obj.get_parent()

parental.short_description = "Parent"


class OrderedContentSetViewSet(SnippetViewSet):
model = OrderedContentSet
Expand Down