diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5bac20c..c65e1460 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python: ['3.9', '3.10', '3.11', '3.12'] database: ['postgres'] services: @@ -110,6 +110,6 @@ jobs: run: | coverage run testmanage.py test - name: 'Upload coverage to Codecov' - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: fail_ci_if_error: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c7f3b85..2f0059ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Support for Wagtail 6.1 ([#797](https://github.com/wagtail/wagtail-localize/pull/797)) & 6.2 ([#813](https://github.com/wagtail/wagtail-localize/pull/813)) + +### Removed + +- Support for Django < 4.2 ([#797](https://github.com/wagtail/wagtail-localize/pull/797)) +- Support for Python < 3.9 ([#813](https://github.com/wagtail/wagtail-localize/pull/813)) + ## [1.9] - 2024-04-03 ### Added diff --git a/README.md b/README.md index 11ee77e1..ed34faa4 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ We'll be at Wagtail Space US this year! The Call for Participation and Registrat Wagtail Localize requires the following: -- Python (3.8, 3.9, 3.10, 3.11) -- Django (3.2, 4.2, 5.0) -- Wagtail (5.2, 6.0) with [internationalisation enabled](https://docs.wagtail.org/en/stable/advanced_topics/i18n.html#configuration) +- Python (3.9, 3.10, 3.11) +- Django (4.2, 5.0, 5.1) +- Wagtail (5.2, 6.1) with [internationalisation enabled](https://docs.wagtail.org/en/stable/advanced_topics/i18n.html#configuration) - [wagtail-modeladmin](https://pypi.org/project/wagtail-modeladmin/) if `using wagtail_localize.modeladmin` and Wagtail >= 5.2 ## Installation diff --git a/docs/how-to/modeladmin.md b/docs/how-to/modeladmin.md index f7f0f48e..4d8b60fe 100644 --- a/docs/how-to/modeladmin.md +++ b/docs/how-to/modeladmin.md @@ -18,8 +18,8 @@ INSTALLED_APPS = [ When registering your custom models you can use the supplied `TranslatableModelAdmin` in place of Wagtail's `ModelAdmin` class. ```python -from wagtail.contrib.modeladmin.options import modeladmin_register from wagtail_localize.modeladmin.options import TranslatableModelAdmin +from wagtail_modeladmin.options import modeladmin_register from .models import MyTranslatableModel diff --git a/package-lock.json b/package-lock.json index 1132c262..84c9cd12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wagtail-localize-admin", - "version": "1.5.0", + "version": "1.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wagtail-localize-admin", - "version": "1.5.0", + "version": "1.9.0", "license": "ISC", "dependencies": { "react": "^16.14.0", diff --git a/pyproject.toml b/pyproject.toml index d7c18b78..27bde8d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,23 +16,22 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Framework :: Django", - "Framework :: Django :: 3.2", "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", + "Framework :: Django :: 5.1", "Framework :: Wagtail", - "Framework :: Wagtail :: 4", - "Framework :: Wagtail :: 5" + "Framework :: Wagtail :: 5", + "Framework :: Wagtail :: 6" ] dynamic = ["version"] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ - "Django>=3.2,<5.1", + "Django>=4.2,<6.0", "Wagtail>=5.2", "polib>=1.1,<2.0", "typing_extensions>=4.0" diff --git a/tox.ini b/tox.ini index 480b26bd..b81418d0 100644 --- a/tox.ini +++ b/tox.ini @@ -2,17 +2,16 @@ min_version = 4.0 envlist = - python3.10-django3.2-wagtail5.2-postgres15 - python{3.8,3.9,3.10,3.11,3.12}-django{4.2}-wagtail{5.2,6.0}-postgres15 - python{3.10,3.11,3.12}-django{5.0}-wagtail{5.2,6.0}-postgres15 + python{3.9,3.10,3.11,3.12}-django4.2-wagtail{5.2,6.1,6.2}-postgres15 + python{3.10,3.11,3.12}-django5.0-wagtail{5.2,6.1,6.2}-postgres15 + python{3.12}-django5.1-wagtail{6.2}-postgres15 # note: we're running a subset of the test with sqlite - python3.10-django3.2-wagtail5.2-sqlite - python3.11-django4.2-wagtail{5.2,6.0}-sqlite - python3.12-django5.0-wagtail{5.2,6.0}-sqlite + python3.11-django4.2-wagtail{5.2,6.1,6.2}-sqlite + python3.12-django5.0-wagtail{5.2,6.1,6.2}-sqlite + python3.12-django5.1-wagtail{6.2}-sqlite [gh-actions] python = - 3.8: python3.8 3.9: python3.9 3.10: python3.10 3.11: python3.11 @@ -39,12 +38,13 @@ setenv = extras = testing deps = - django3.2: Django>=3.2,<3.3 django4.2: Django>=4.2,<5.0 django5.0: Django>=5.0,<5.1 + django5.1: Django>=5.1,<5.2 wagtail5.2: wagtail>=5.2.2,<5.3 - wagtail6.0: wagtail>=6.0,<6.1 + wagtail6.1: wagtail>=6.1,<6.2 + wagtail6.2: wagtail>=6.2,<6.3 wagtailmain: git+https://github.com/wagtail/wagtail.git postgres: psycopg2>=2.9 @@ -75,7 +75,8 @@ commands = description = An interactive environment for local testing purposes basepython = python3.11 deps = - wagtail>=5.2,<6.0 + wagtail>=5.2,<6.3 + Django>=4.2,<5.2 commands_pre = python {toxinidir}/testmanage.py makemigrations @@ -94,7 +95,7 @@ basepython = python3.11 # always generate with the min supported versions deps = - Django>=3.2,<3.3 + Django>=4.2,<5.0 wagtail>=5.2,<6.0 commands = diff --git a/wagtail_localize/locales/templates/wagtaillocales/confirm_delete.html b/wagtail_localize/locales/templates/wagtaillocales/confirm_delete.html index fe470f36..3c9c5153 100644 --- a/wagtail_localize/locales/templates/wagtaillocales/confirm_delete.html +++ b/wagtail_localize/locales/templates/wagtaillocales/confirm_delete.html @@ -1,22 +1,18 @@ {% extends "wagtailadmin/generic/confirm_delete.html" %} {% load i18n %} -{% block content %} - {% include "wagtailadmin/shared/header.html" with title=view.page_title subtitle=view.get_page_subtitle icon=view.header_icon %} - -
- {% if can_delete %} -

{{ view.confirmation_message }}

- -
- {% csrf_token %} - - {% trans "Back" %} -
- {% else %} -

{{ view.cannot_delete_message }}

+{% block main_content %} + {% if can_delete %} +

{{ view.confirmation_message }}

+
+ {% csrf_token %} + {% trans "Back" %} - {% endif %} -
+ + {% else %} +

{{ view.cannot_delete_message }}

+ + {% trans "Back" %} + {% endif %} {% endblock %} diff --git a/wagtail_localize/templates/wagtail_localize/admin/translations_report_results.html b/wagtail_localize/templates/wagtail_localize/admin/translations_report_results.html new file mode 100644 index 00000000..97fb0af3 --- /dev/null +++ b/wagtail_localize/templates/wagtail_localize/admin/translations_report_results.html @@ -0,0 +1,51 @@ +{% extends 'wagtailadmin/reports/base_report_results.html' %} +{% load i18n wagtailadmin_tags %} + +{% block results %} + + + + + + + + + + + {% for translation in object_list %} + + + + + + + {% endfor %} + +
+ {% trans 'Content type' %} + + {% trans 'Source' %} + + {% trans 'Target' %} + + {% trans 'Status' %} +
+ {{ translation.source.specific_content_type.name|capfirst }} + + + {{ translation.source.object_repr }} ({{ translation.source.locale }}) + + + {% with translation.get_target_instance as target_instance %} + + {{ target_instance.get_admin_display_title|default:target_instance }} ({{ translation.target_locale }}) + + {% endwith %} + + {{ translation.get_status_display }} +
+{% endblock %} + +{% block no_results_message %} +

{% trans "No translations found." %}

+{% endblock %} diff --git a/wagtail_localize/tests/test_edit_translation.py b/wagtail_localize/tests/test_edit_translation.py index d4c5918e..7a7bf893 100644 --- a/wagtail_localize/tests/test_edit_translation.py +++ b/wagtail_localize/tests/test_edit_translation.py @@ -25,7 +25,7 @@ ) from rest_framework.settings import api_settings from rest_framework.test import APITestCase -from wagtail.admin.panels import FieldPanel +from wagtail.admin.panels import FieldPanel, TitleFieldPanel from wagtail.blocks import StreamValue from wagtail.documents.models import Document from wagtail.images.models import Image @@ -1506,7 +1506,7 @@ def test_edit_page_translation_with_missing_panel(self): # Hide fields that don't have a panel to edit them with previous_panels = TestPage.content_panels TestPage.content_panels = [ - FieldPanel("title"), + TitleFieldPanel("title"), FieldPanel("test_textfield"), ] TestPage.get_edit_handler.cache_clear() diff --git a/wagtail_localize/views/report.py b/wagtail_localize/views/report.py index bcd7b508..da576221 100644 --- a/wagtail_localize/views/report.py +++ b/wagtail_localize/views/report.py @@ -6,6 +6,7 @@ from django_filters.constants import EMPTY_VALUES from django_filters.fields import ModelChoiceField from modelcluster.fields import ParentalKey +from wagtail import VERSION as WAGTAIL_VERSION from wagtail.admin.filters import WagtailFilterSet from wagtail.admin.views.reports import ReportView from wagtail.coreutils import get_content_languages @@ -135,9 +136,40 @@ class Meta: fields = ["content_type", "source_title", "source_locale", "target_locale"] +def _adapt_wagtail_report_attributes(cls): + """ + A class decorator that adapts ReportView-derived classes for compatibility + with multiple versions of Wagtail by conditionally assigning attributes + based on the Wagtail version. This includes setting appropriate titles, + and adjusting template names and URL names for AJAX support since Wagtail 6.2. + + Attributes adjusted: + - `title` or `page_title` based on Wagtail version for the display name of the report. + - For Wagtail 6.2 and above, additional attributes like `results_template_name`, + `index_results_url_name`, and `index_url_name` are set to support AJAX updates + and utilize the `wagtail.admin.ui.tables` framework. + """ + if WAGTAIL_VERSION < (6, 2): + cls.title = gettext_lazy("Translations") + else: + # The `title` attr was **changed** to `page_title` in Wagtail 6.2 + cls.page_title = gettext_lazy("Translations") + # The `results_template_name` attr was **added** in Wagtail 6.2 + # to support updating the listing via AJAX upon filtering and + # to allow the use of the `wagtail.admin.ui.tables` framework. + cls.results_template_name = ( + "wagtail_localize/admin/translations_report_results.html" + ) + # The `index_results_url_name` attr was **added** in Wagtail 6.2 + # to support updating the listing via AJAX upon filtering. + cls.index_results_url_name = "wagtail_localize:translations_report_results" + cls.index_url_name = "wagtail_localize:translations_report" + return cls + + +@_adapt_wagtail_report_attributes class TranslationsReportView(ReportView): template_name = "wagtail_localize/admin/translations_report.html" - title = gettext_lazy("Translations") header_icon = "site" filterset_class = TranslationsReportFilterSet diff --git a/wagtail_localize/wagtail_hooks.py b/wagtail_localize/wagtail_hooks.py index 688b7202..2a0455c9 100644 --- a/wagtail_localize/wagtail_hooks.py +++ b/wagtail_localize/wagtail_hooks.py @@ -10,6 +10,7 @@ from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy from django.views.i18n import JavaScriptCatalog +from wagtail import VERSION as WAGTAIL_VERSION from wagtail import hooks from wagtail.admin.action_menu import ActionMenuItem as PageActionMenuItem from wagtail.admin.menu import MenuItem @@ -117,6 +118,16 @@ def register_admin_urls(): ), ] + if WAGTAIL_VERSION >= (6, 2): + # Add a results-only view to add support for AJAX-based filtering + urls.append( + path( + "reports/translations/results/", + report.TranslationsReportView.as_view(results_only=True), + name="translations_report_results", + ), + ) + return [ path( "localize/",