diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99516f7..c0468cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,21 +7,26 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - wagtail-version: - - "4.1" - - "4.2" - - "5.0" - - "5.1" - - "5.2" + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + wagtail-version: ["5.2", "6.2", "6.3"] + django-version: ["4.2", "5.0", "5.1"] + exclude: + - python-version: "3.13" + django-version: "4.2" + - python-version: "3.13" + django-version: "5.0" + - python-version: "3.9" + django-version: "5.0" + - python-version: "3.9" + django-version: "5.1" + - wagtail-version: "5.2" + django-version: "5.1" + - wagtail-version: "6.2" + django-version: "5.1" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -37,7 +42,7 @@ jobs: runs-on: ubuntu-latest needs: test steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: psf/black@stable with: options: "--check --verbose" @@ -48,10 +53,10 @@ jobs: runs-on: ubuntu-latest needs: test steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -62,10 +67,10 @@ jobs: runs-on: ubuntu-latest needs: [test, lint-black, lint-isort] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/CHANGELOG.md b/CHANGELOG.md index 8239917..c1a4f42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + ### Added +- Add Wagtail 6.x support (@katdom13) +- Add Python 3.11 support (@katdom13) + ### Changed -### Fixed +- Apply Django 5.0 upgrade considerations (@katdom13) + ### Removed +- Drop Wagtail < 5.2 support (@katdom13) ## [1.5.0] - 2023-12-22 ### Added diff --git a/MANIFEST.in b/MANIFEST.in index 1771576..b356db2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include README.md LICENSE runtests.py -include wagtail_color_panel/static/wagtail_color_panel/css/color-input-widget.css +include wagtail_color_panel/static/** +include wagtail_color_panel/templates/** prune img* diff --git a/docs/1_getting_started.md b/docs/1_getting_started.md index 441c7fa..32edb93 100644 --- a/docs/1_getting_started.md +++ b/docs/1_getting_started.md @@ -2,8 +2,8 @@ ### Requirements -- Python 3.8+ -- Wagtail 4.1+ and Django 3.2+ +- Python 3.9+ +- Wagtail 5.2+ and Django 4.2+ - [A browser that supports `input type="color"`](https://caniuse.com/#feat=input-color) diff --git a/docs/3_adding_to_a_streamfield.md b/docs/3_adding_to_a_streamfield.md index 50efd7c..e9c26ce 100644 --- a/docs/3_adding_to_a_streamfield.md +++ b/docs/3_adding_to_a_streamfield.md @@ -11,7 +11,7 @@ from wagtail_color_panel.blocks import NativeColorBlock class MyStreamFieldPage(Page): body = StreamField([ ('color', NativeColorBlock(default="#000000")), - ], use_json_field=True) + ], use_json_field=True) # use_json_field is not required with Wagtail 6.0+ content_panels = Page.content_panels + [ FieldPanel('body'), diff --git a/docs/4_reference.md b/docs/4_reference.md index 13bde1a..bcacb3c 100644 --- a/docs/4_reference.md +++ b/docs/4_reference.md @@ -74,7 +74,7 @@ from wagtail_color_panel.blocks import NativeColorBlock class MyStreamFieldPage(Page): body = StreamField([ ('color', NativeColorBlock(default="#000000")), - ], use_json_field=True) + ], use_json_field=True) # use_json_field is not required with Wagtail 6.0+ content_panels = Page.content_panels + [ FieldPanel('body'), diff --git a/setup.py b/setup.py index 77fa3e0..964ad27 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import find_packages, setup -install_requires = ["wagtail>=4.1"] +install_requires = ["wagtail>=5.2"] tests_require = ["pytest-django", "wagtail-factories", "pytest"] @@ -39,20 +39,24 @@ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "Framework :: Django :: 5.1", "Framework :: Wagtail", - "Framework :: Wagtail :: 4", "Framework :: Wagtail :: 5", + "Framework :: Wagtail :: 6", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "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", + "Programming Language :: Python :: 3.13", "Topic :: Utilities", ], setup_requires=["setuptools_scm", "pytest-runner"], - python_requires=">=3.8", + python_requires=">=3.9", ) diff --git a/tests/test_block.py b/tests/test_block.py index ad23550..d06a092 100644 --- a/tests/test_block.py +++ b/tests/test_block.py @@ -1,5 +1,6 @@ from django.core.exceptions import ValidationError from django.test import TestCase +from wagtail import VERSION as WAGTAIL_VERSION from wagtail.test.utils import WagtailTestUtils from wagtail_color_panel.blocks import NativeColorBlock @@ -15,7 +16,11 @@ def test_color_block_render(self): def test_form_uses_proper_input_type(self): block = NativeColorBlock() - html = block.field.widget.render_html(name="cat", value="#333333", attrs={}) + + if WAGTAIL_VERSION >= (6, 0): + html = block.field.widget.render(name="cat", value="#333333", attrs={}) + else: + html = block.field.widget.render_html(name="cat", value="#333333", attrs={}) self.assertEqual(block.field.widget.__class__, ColorInputWidget) self.assertIn('type="color"', html) diff --git a/wagtail_color_panel/static/wagtail_color_panel/js/color-input-controller.js b/wagtail_color_panel/static/wagtail_color_panel/js/color-input-controller.js new file mode 100644 index 0000000..0ee39f1 --- /dev/null +++ b/wagtail_color_panel/static/wagtail_color_panel/js/color-input-controller.js @@ -0,0 +1,9 @@ +// wagtail_color_panel/static/wagtail_color_panel/js/color-input-controller.js + +class ColorInputController extends window.StimulusModule.Controller { + connect() { + new ColorInputWidget(this.element.id); + } +} + +window.wagtail.app.register('color-input', ColorInputController); diff --git a/wagtail_color_panel/widgets.py b/wagtail_color_panel/widgets.py index e1db39e..5f3e1ec 100644 --- a/wagtail_color_panel/widgets.py +++ b/wagtail_color_panel/widgets.py @@ -2,8 +2,8 @@ from django.forms import widgets from django.utils.safestring import mark_safe +from wagtail import VERSION as WAGTAIL_VERSION from wagtail.telepath import register -from wagtail.utils.widgets import WidgetWithScript from wagtail.widget_adapters import WidgetAdapter @@ -49,29 +49,65 @@ def render(self, name, value, attrs=None, renderer=None): ) -class ColorInputWidget(WidgetWithScript, widgets.TextInput): - template_name = "wagtail_color_panel/widgets/color-input-widget.html" - - def __init__(self, attrs=None): - default_attrs = { - "class": "color-input-widget__text-input", - } - attrs = attrs or {} - attrs = {**default_attrs, **attrs} - super().__init__(attrs=attrs) - - def render_js_init(self, id_, name, value): - return "new ColorInputWidget({0});".format(json.dumps(id_)) +if WAGTAIL_VERSION >= (6, 0): # type: ignore + from django.forms import Media + + class ColorInputWidget(widgets.TextInput): # type: ignore + template_name = "wagtail_color_panel/widgets/color-input-widget.html" + + def __init__(self, attrs=None): + default_attrs = { + "class": "color-input-widget__text-input", + } + attrs = attrs or {} + attrs = {**default_attrs, **attrs} + super().__init__(attrs=attrs) + + def build_attrs(self, *args, **kwargs): + attrs = super().build_attrs(*args, **kwargs) + attrs["data-controller"] = "color-input" + return attrs + + @property + def media(self): + return Media( + css={ + "all": [ + "wagtail_color_panel/css/color-input-widget.css", + ] + }, + js=[ + "wagtail_color_panel/js/color-input-widget.js", + "wagtail_color_panel/js/color-input-controller.js", + ], + ) - class Media: - css = { - "all": [ - "wagtail_color_panel/css/color-input-widget.css", +else: + from wagtail.utils.widgets import WidgetWithScript + + class ColorInputWidget(WidgetWithScript, widgets.TextInput): + template_name = "wagtail_color_panel/widgets/color-input-widget.html" + + def __init__(self, attrs=None): + default_attrs = { + "class": "color-input-widget__text-input", + } + attrs = attrs or {} + attrs = {**default_attrs, **attrs} + super().__init__(attrs=attrs) + + def render_js_init(self, id_, name, value): + return "new ColorInputWidget({0});".format(json.dumps(id_)) + + class Media: + css = { + "all": [ + "wagtail_color_panel/css/color-input-widget.css", + ] + } + js = [ + "wagtail_color_panel/js/color-input-widget.js", ] - } - js = [ - "wagtail_color_panel/js/color-input-widget.js", - ] class ColorInputWidgetAdapter(WidgetAdapter):