Skip to content

Commit 39bd875

Browse files
Merge pull request #3006 from UKHSA-Internal/task/new-cms-page-type/cdd-3129
Task/new cms page type/cdd 3129
2 parents de3591d + 1ce74ad commit 39bd875

File tree

14 files changed

+1337
-0
lines changed

14 files changed

+1337
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"id": 83,
3+
"meta": {
4+
"seo_title": "Health topics",
5+
"search_description": "",
6+
"type": "topics_list.TopicsListPage",
7+
"detail_url": "https://http:/api/pages/83/",
8+
"html_url": "https://http://localhost:3000/health-topics/",
9+
"slug": "health-topics",
10+
"show_in_menus": false,
11+
"first_published_at": "2026-02-16T16:00:23.483810Z",
12+
"alias_of": null,
13+
"parent": {
14+
"id": 3,
15+
"meta": {
16+
"type": "home.UKHSARootPage",
17+
"detail_url": "https://http:/api/pages/3/",
18+
"html_url": null
19+
},
20+
"title": "UKHSA Dashboard Root"
21+
}
22+
},
23+
"title": "health topics",
24+
"body": "",
25+
"seo_change_frequency": 5,
26+
"seo_priority": "0.5",
27+
"last_updated_at": "2026-02-16T16:00:23.483810Z",
28+
"last_published_at": "2026-02-16T16:00:23.483810Z",
29+
"active_announcements": [],
30+
"page_description": "<p data-block-key=\"onu6j\">The UKHSA data dashboard shares public health data in a simple, inclusive and accessible way.</p>"
31+
}

cms/topics_list/__init__.py

Whitespace-only changes.

cms/topics_list/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class TopicsListConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "cms.topics_list"

cms/topics_list/managers.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
This file contains the custom QuerySet and Manager classes associated with the `TopicsList` model.
3+
4+
Note that the application layer should only call into the `Manager` class.
5+
The application should not interact directly with the `QuerySet` class.
6+
"""
7+
8+
from django.db import models
9+
from wagtail.models import PageManager
10+
from wagtail.query import PageQuerySet
11+
12+
EXPECTED_TOPICS_LIST_PAGE_SLUG = "health-topics"
13+
14+
15+
class TopicsListPageQuerySet(PageQuerySet):
16+
"""Custom queryset for which can be used by the `TopicsListPageManager`."""
17+
18+
def get_topics_list_page(self) -> models.QuerySet:
19+
"""Gets the designated health-topics page.
20+
21+
Returns:
22+
QuerySet: A queryset of the individual topics_list page.
23+
Examples:
24+
`<TopicsListPageQuerySet [<TopicsListPage: Health Topics>, ... ]`
25+
"""
26+
return self.filter(slug=EXPECTED_TOPICS_LIST_PAGE_SLUG)
27+
28+
29+
class TopicsListPageManager(PageManager):
30+
"""Custom model manager class for the `TopicsListPageManager`."""
31+
32+
def get_queryset(self) -> TopicsListPageQuerySet:
33+
return TopicsListPageQuerySet(self.model, using=self._db)
34+
35+
def get_topics_list_page(self):
36+
"""Gets the designated health topics page.
37+
38+
Returns:
39+
The designated topics list page object
40+
which has the slug of `health-topics`
41+
"""
42+
return self.get_queryset().get_topics_list_page().last()

cms/topics_list/migrations/0001_initial.py

Lines changed: 1043 additions & 0 deletions
Large diffs are not rendered by default.

cms/topics_list/migrations/__init__.py

Whitespace-only changes.

cms/topics_list/models.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from django.db import models
2+
from modelcluster.fields import ParentalKey
3+
from wagtail.admin.panels import FieldPanel, ObjectList, TabbedInterface
4+
from wagtail.api import APIField
5+
from wagtail.fields import RichTextField
6+
from wagtail.search import index
7+
8+
from cms.dashboard.models import AVAILABLE_RICH_TEXT_FEATURES, UKHSAPage
9+
from cms.dynamic_content import help_texts
10+
from cms.dynamic_content.access import ALLOWABLE_BODY_CONTENT_SECTION_LINK
11+
from cms.dynamic_content.announcements import Announcement
12+
from cms.topics_list.managers import TopicsListPageManager
13+
14+
15+
class TopicsListPage(UKHSAPage):
16+
max_count = 1
17+
page_description = RichTextField(
18+
features=AVAILABLE_RICH_TEXT_FEATURES,
19+
blank=True,
20+
null=True,
21+
help_text=help_texts.PAGE_DESCRIPTION_FIELD,
22+
)
23+
body = ALLOWABLE_BODY_CONTENT_SECTION_LINK
24+
25+
objects = TopicsListPageManager()
26+
27+
# Search index configuration
28+
search_fields = UKHSAPage.search_fields + [
29+
index.SearchField("title"),
30+
]
31+
32+
# Editor panels
33+
content_panels = UKHSAPage.content_panels + [
34+
FieldPanel("page_description"),
35+
FieldPanel("body"),
36+
]
37+
38+
# Sets which fields to expose on the API
39+
api_fields = UKHSAPage.api_fields + [
40+
APIField("title"),
41+
APIField("page_description"),
42+
APIField("body"),
43+
APIField("last_published_at"),
44+
APIField("search_description"),
45+
]
46+
47+
edit_handler = TabbedInterface(
48+
[
49+
ObjectList(content_panels, heading="Content"),
50+
ObjectList(UKHSAPage.announcement_content_panels, heading="Announcements"),
51+
ObjectList(UKHSAPage.promote_panels, heading="Promote"),
52+
]
53+
)
54+
55+
@classmethod
56+
def is_previewable(cls):
57+
"""Returns False. This is a headline CMS, preview panel is not supported ."""
58+
return False
59+
60+
61+
class TopicsListPageAnnouncements(Announcement):
62+
page = ParentalKey(
63+
TopicsListPage,
64+
on_delete=models.SET_NULL,
65+
null=True,
66+
related_name="announcements",
67+
)

metrics/api/settings/default.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"metrics.api",
5353
"cms.home",
5454
"cms.topic",
55+
"cms.topics_list",
5556
"cms.dashboard",
5657
"cms.common",
5758
"cms.composite",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import factory
2+
3+
from cms.dashboard.management.commands.build_cms_site_helpers.pages import (
4+
open_example_page_response,
5+
)
6+
from tests.fakes.models.cms.topics_list import FakeTopicsListPage
7+
8+
9+
class FakeTopicsListPageFactory(factory.Factory):
10+
"""
11+
Factory for creating `FakeTopicListPage` instance for tests
12+
"""
13+
14+
class Meta:
15+
model = FakeTopicsListPage
16+
17+
@classmethod
18+
def build_blank_page(cls, **kwargs):
19+
return cls.build(**kwargs)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from cms.topics_list.models import TopicsListPage
2+
from tests.fakes.models.fake_model_meta import FakeMeta
3+
4+
5+
class FakeTopicsListPage(TopicsListPage):
6+
"""
7+
A fake version of the Django model `TopicsListPage`
8+
which has had its dependencies altered so that it does not interact with the database
9+
"""
10+
11+
Meta = FakeMeta
12+
13+
def __init__(self, **kwargs):
14+
"""
15+
Constructor takes the same arguments as a normal `TopicsListPage` model.
16+
"""
17+
super().__init__(content_type_id=1, **kwargs)

0 commit comments

Comments
 (0)