diff --git a/docs/extending/adding_reports.md b/docs/extending/adding_reports.md index 932f211ab9..6711b48872 100644 --- a/docs/extending/adding_reports.md +++ b/docs/extending/adding_reports.md @@ -76,13 +76,16 @@ In this example, we'll change this to a new template in a later section. .. versionadded:: 6.2 The ``results_template_name`` attribute was added to support updating the listing via AJAX upon filtering and to allow the use of the ``wagtail.admin.ui.tables`` framework. -.. attribute:: title +.. attribute:: page_title (string) The name of your report, which will be displayed in the header. For our example, we'll set it to ``"Pages with unpublished changes"``. +.. versionchanged:: 6.2 + The ``title`` attribute was renamed to ``page_title``. + .. attribute:: header_icon (string) @@ -250,7 +253,7 @@ class UnpublishedChangesReportView(PageReportView): index_results_url_name = "unpublished_changes_report_results" header_icon = 'doc-empty-inverse' results_template_name = 'reports/unpublished_changes_report_results.html' - title = "Pages with unpublished changes" + page_title = "Pages with unpublished changes" list_export = PageReportView.list_export + ['last_published_at'] export_headings = dict(last_published_at='Last Published', **PageReportView.export_headings) diff --git a/docs/releases/6.2.md b/docs/releases/6.2.md index 5411fbc87b..c23638abee 100644 --- a/docs/releases/6.2.md +++ b/docs/releases/6.2.md @@ -152,6 +152,16 @@ As a result, a number of changes have been made to the `ReportView` and `PageRep If you have custom report views as documented in [](adding_reports), you will need to make the following changes. +#### Change `title` to `page_title` + +The `title` attribute on the view class should be renamed to `page_title`: + +```diff + class UnpublishedChangesReportView(PageReportView): +- title = "Pages with unpublished changes" ++ page_title = "Pages with unpublished changes" +``` + #### Set up the results-only view Set the `index_url_name` and `index_results_url_name` attributes on the view class: diff --git a/wagtail/admin/tests/test_reports_views.py b/wagtail/admin/tests/test_reports_views.py index a6050c28c6..820f4f8102 100644 --- a/wagtail/admin/tests/test_reports_views.py +++ b/wagtail/admin/tests/test_reports_views.py @@ -33,6 +33,7 @@ from wagtail.test.testapp.models import ( ) from wagtail.test.utils import WagtailTestUtils from wagtail.test.utils.template_tests import AdminTemplateTestUtils +from wagtail.utils.deprecation import RemovedInWagtail70Warning class BaseReportViewTestCase(AdminTemplateTestUtils, WagtailTestUtils, TestCase): @@ -97,6 +98,14 @@ class BaseReportViewTestCase(AdminTemplateTestUtils, WagtailTestUtils, TestCase) else: self.assertBreadcrumbsItemsRendered(breadcrumbs, html) + def assertPageTitle(self, soup, title): + page_title = soup.select_one("title") + if self.results_only: + self.assertIsNone(page_title) + else: + self.assertIsNotNone(page_title) + self.assertEqual(page_title.text.strip(), title) + class TestLockedPagesView(BaseReportViewTestCase): url_name = "wagtailadmin_reports:locked_pages" @@ -131,6 +140,7 @@ class TestLockedPagesView(BaseReportViewTestCase): self.assertEqual(locked_by_options[0].text, "---------") self.assertEqual(locked_by_options[0].get("value"), "") self.assertActiveFilterNotRendered(soup) + self.assertPageTitle(soup, "Locked pages - Wagtail") parent_page = Page.objects.first() parent_page.add_child( @@ -500,6 +510,7 @@ class TestFilteredLogEntriesView(BaseReportViewTestCase): soup = self.get_soup(response.content) self.assertActiveFilterNotRendered(soup) + self.assertPageTitle(soup, "Site history - Wagtail") # The editor should not see the Advert's log entries. self.login(user=self.editor) @@ -797,6 +808,41 @@ class TestFilteredLogEntriesView(BaseReportViewTestCase): self.assertEqual(response.status_code, 200) + def test_deprecated_title_attribute(self): + # Remove this test when the deprecation ends + with mock.patch.object( + LogEntriesView, + "page_title", + return_value=None, + new_callable=mock.PropertyMock, + ), mock.patch.object( + LogEntriesView, + "title", + return_value="Deprecated page title", + new_callable=mock.PropertyMock, + ): + with self.assertWarnsMessage( + RemovedInWagtail70Warning, + "The `title` attribute in `LogEntriesView` (a `ReportView` subclass) is " + "deprecated. Use `page_title` instead.", + ): + self.assertEqual(LogEntriesView.title, "Deprecated page title") + self.assertIsNone(LogEntriesView.page_title) + response = self.get() + self.assertEqual(response.status_code, 200) + self.assertPageTitle( + self.get_soup(response.content), + "Deprecated page title - Wagtail", + ) + self.assertEqual( + response.context["page_title"], + "Deprecated page title", + ) + self.assertEqual( + response.context["title"], + "Deprecated page title", + ) + class TestFilteredLogEntriesResultsView(TestFilteredLogEntriesView): url_name = "wagtailadmin_reports:site_history_results" @@ -855,6 +901,7 @@ class TestAgingPagesView(BaseReportViewTestCase): ) soup = self.get_soup(response.content) self.assertActiveFilterNotRendered(soup) + self.assertPageTitle(soup, "Aging pages - Wagtail") def test_displays_only_published_pages(self): response = self.get() @@ -1130,6 +1177,7 @@ class PageTypesUsageReportViewTest(BaseReportViewTestCase): ) soup = self.get_soup(response.content) self.assertActiveFilterNotRendered(soup) + self.assertPageTitle(soup, "Page types usage - Wagtail") def test_displays_only_page_types(self): """Asserts that the correct models are included in the queryset.""" diff --git a/wagtail/admin/tests/test_workflows.py b/wagtail/admin/tests/test_workflows.py index a9e21f7f84..35337953ac 100644 --- a/wagtail/admin/tests/test_workflows.py +++ b/wagtail/admin/tests/test_workflows.py @@ -2909,6 +2909,9 @@ class TestPageWorkflowReport(BasePageWorkflowTests): def assertBreadcrumbs(self, breadcrumbs, html): self.assertBreadcrumbsItemsRendered(breadcrumbs, html) + def assertPageTitle(self, soup, title): + self.assertEqual(soup.select_one("title").text.strip(), title) + def get(self, url, params=None): return self.client.get(url, params) @@ -2953,6 +2956,7 @@ class TestPageWorkflowReport(BasePageWorkflowTests): ) self.assertEqual(list(by_task_link.children)[-1].strip(), "By task") self.assertIsNone(soup.select_one(".w-active-filters")) + self.assertPageTitle(soup, "Workflows - Wagtail") response = self.get(reverse(self.workflow_tasks_url_name)) self.assertEqual(response.status_code, 200) @@ -2972,6 +2976,7 @@ class TestPageWorkflowReport(BasePageWorkflowTests): ) self.assertEqual(list(by_task_link.children)[-1].strip(), "By workflow") self.assertIsNone(soup.select_one(".w-active-filters")) + self.assertPageTitle(soup, "Workflow tasks - Wagtail") def test_workflow_report_filtered(self): # the moderator can review the task, so the workflow state should show up even when reports are filtered by reviewable @@ -3161,6 +3166,9 @@ class TestPageWorkflowReportResults(TestPageWorkflowReport): def assertBreadcrumbs(self, breadcrumbs, html): self.assertBreadcrumbsNotRendered(html) + def assertPageTitle(self, soup, title): + self.assertIsNone(soup.select_one("title")) + def get(self, url, params=None): params = params or {} params["_w_filter_fragment"] = "true" diff --git a/wagtail/admin/views/reports/aging_pages.py b/wagtail/admin/views/reports/aging_pages.py index eb496f0121..d9d829370c 100644 --- a/wagtail/admin/views/reports/aging_pages.py +++ b/wagtail/admin/views/reports/aging_pages.py @@ -30,7 +30,7 @@ class AgingPagesReportFilterSet(WagtailFilterSet): class AgingPagesView(PageReportView): results_template_name = "wagtailadmin/reports/aging_pages_results.html" - title = _("Aging pages") + page_title = _("Aging pages") header_icon = "time" filterset_class = AgingPagesReportFilterSet index_url_name = "wagtailadmin_reports:aging_pages" diff --git a/wagtail/admin/views/reports/audit_logging.py b/wagtail/admin/views/reports/audit_logging.py index 6731bb19b9..94f8455a6f 100644 --- a/wagtail/admin/views/reports/audit_logging.py +++ b/wagtail/admin/views/reports/audit_logging.py @@ -74,7 +74,7 @@ class SiteHistoryReportFilterSet(PageHistoryFilterSet): class LogEntriesView(ReportView): results_template_name = "wagtailadmin/reports/site_history_results.html" - title = _("Site history") + page_title = _("Site history") header_icon = "history" filterset_class = SiteHistoryReportFilterSet index_url_name = "wagtailadmin_reports:site_history" diff --git a/wagtail/admin/views/reports/base.py b/wagtail/admin/views/reports/base.py index 9161d56344..3f800cc4d7 100644 --- a/wagtail/admin/views/reports/base.py +++ b/wagtail/admin/views/reports/base.py @@ -1,7 +1,10 @@ +from warnings import warn + from django.utils.translation import gettext_lazy as _ from wagtail.admin.views.generic.base import BaseListingView from wagtail.admin.views.mixins import SpreadsheetExportMixin +from wagtail.utils.deprecation import RemovedInWagtail70Warning class ReportView(SpreadsheetExportMixin, BaseListingView): @@ -17,9 +20,17 @@ class ReportView(SpreadsheetExportMixin, BaseListingView): ] def get_page_title(self): + if self.page_title: + return self.page_title # WagtailAdminTemplateMixin uses `page_title`, but the documented approach - # for ReportView uses `title`, so we change the reference here to allow - # using the generic base template while keeping the `title` attribute + # for ReportView used `title`, so we need to support both during the + # deprecation period. When `title` is removed, this and the `get_context_data` + # overrides can be removed. + warn( + f"The `title` attribute in `{self.__class__.__name__}` (a `ReportView` subclass) " + "is deprecated. Use `page_title` instead.", + RemovedInWagtail70Warning, + ) return self.title def get_filtered_queryset(self): @@ -41,7 +52,7 @@ class ReportView(SpreadsheetExportMixin, BaseListingView): def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) - context["title"] = self.title + context["title"] = self.get_page_title() return context def render_to_response(self, context, **response_kwargs): diff --git a/wagtail/admin/views/reports/locked_pages.py b/wagtail/admin/views/reports/locked_pages.py index 1c841a5ef4..b8d37f3647 100644 --- a/wagtail/admin/views/reports/locked_pages.py +++ b/wagtail/admin/views/reports/locked_pages.py @@ -35,7 +35,7 @@ class LockedPagesReportFilterSet(WagtailFilterSet): class LockedPagesView(PageReportView): results_template_name = "wagtailadmin/reports/locked_pages_results.html" - title = _("Locked pages") + page_title = _("Locked pages") header_icon = "lock" list_export = PageReportView.list_export + [ "locked_at", diff --git a/wagtail/admin/views/reports/page_types_usage.py b/wagtail/admin/views/reports/page_types_usage.py index acdbda5e01..7cc0cbc6a4 100644 --- a/wagtail/admin/views/reports/page_types_usage.py +++ b/wagtail/admin/views/reports/page_types_usage.py @@ -97,7 +97,7 @@ class PageTypesUsageReportFilterSet(WagtailFilterSet): class PageTypesUsageReportView(ReportView): results_template_name = "wagtailadmin/reports/page_types_usage_results.html" - title = _("Page types usage") + page_title = _("Page types usage") header_icon = "doc-empty-inverse" filterset_class = PageTypesUsageReportFilterSet index_url_name = "wagtailadmin_reports:page_types_usage" diff --git a/wagtail/admin/views/reports/workflows.py b/wagtail/admin/views/reports/workflows.py index bc16ce9e9b..0cb4e9af10 100644 --- a/wagtail/admin/views/reports/workflows.py +++ b/wagtail/admin/views/reports/workflows.py @@ -140,7 +140,7 @@ class WorkflowTasksReportFilterSet(WagtailFilterSet): class WorkflowView(ReportView): results_template_name = "wagtailadmin/reports/workflow_results.html" - title = _("Workflows") + page_title = _("Workflows") header_icon = "tasks" filterset_class = WorkflowReportFilterSet index_url_name = "wagtailadmin_reports:workflow" @@ -224,7 +224,7 @@ class WorkflowView(ReportView): class WorkflowTasksView(ReportView): results_template_name = "wagtailadmin/reports/workflow_tasks_results.html" - title = _("Workflow tasks") + page_title = _("Workflow tasks") header_icon = "thumbtack" filterset_class = WorkflowTasksReportFilterSet index_url_name = "wagtailadmin_reports:workflow_tasks"