Porównaj commity

..

65 Commity
main ... v6.2.3

Autor SHA1 Wiadomość Data
Matt Westcott 96729c5168 Version bump to 6.2.3 2024-11-01 13:18:16 +00:00
Matt Westcott 89ac3f5cb0 Fill in release date for 6.2.3 2024-11-01 13:17:55 +00:00
Matt Westcott ed19954c8d Fill in release date for 5.2.7 2024-11-01 13:17:15 +00:00
Matt Westcott e592b8e9c6 Release note for in 6.2.3 2024-11-01 13:13:07 +00:00
Thibaud Colas 538c5089e9 Update sphinx-wagtail-theme and search implementation () 2024-11-01 13:10:05 +00:00
Matt Westcott 2271d86fc7 Release note for in 6.2.3 2024-11-01 12:49:30 +00:00
Matt Westcott 37c2224f35 Stop history view from breaking if a log entry's revision is missing ()
e.g. after the purge_revisions management command has been run
2024-11-01 12:48:47 +00:00
Matt Westcott 81f14114a7 Release note for in 6.2.3 2024-11-01 12:31:04 +00:00
Sage Abdullah 0aaec0d7ae Fix error in workflows listing with multiple snippets assigned on PostgreSQL ()
Fixes 
2024-11-01 12:30:09 +00:00
Matt Westcott c6863527ec Release note for in 5.2.7 2024-11-01 12:20:58 +00:00
Thibaud Colas 81701ada3e Release notes for 2024-11-01 12:20:33 +00:00
Thibaud Colas f60b58fea3 Add release note template for 5.2.7 2024-11-01 12:20:14 +00:00
Thibaud Colas ce24331966 Fix link paste detection concatenating URLs. Fix 2024-10-24 10:23:14 +01:00
Thibaud Colas 2ef5767692 Release notes for 2024-10-24 10:22:43 +01:00
Thibaud Colas b5473dccca Add release note template for 6.2.3 2024-10-24 10:21:36 +01:00
Matt Westcott d24bedc961 Version bump to 6.2.2 2024-09-24 10:08:12 +01:00
Matt Westcott 1f92b10bfb Fill in release date for 6.2.2 2024-09-24 10:05:28 +01:00
Matt Westcott a4b957c4a6 Fetch new translations from Transifex 2024-09-24 10:01:29 +01:00
Matt Westcott 187b354a18 Release note for in 6.2.2 2024-09-24 09:26:02 +01:00
Matt Westcott 2c9003ba7b Stop PopularTagsFilter from applying an IN clause when not filtering
Fixes 
2024-09-24 09:23:37 +01:00
Matt Westcott ebbad32cea Docs - Update spelling & reference in release notes for UserViewSet for 6.2.2 2024-09-19 10:14:33 +01:00
Matt Westcott 910dea7044 Release note for in 6.2.2 2024-09-19 10:00:17 +01:00
Matt Westcott ff01041f52 Remove unnecessary filters from redirects index
Fixes 

The filters "Redirect from", "Redirect to a page", "Target page route", "Redirect to any URL", "Automatically created" and "Created at" were introduced when `exclude = []` was set on the filter class in https://github.com/wagtail/wagtail/pull/8851/files#diff-a1afb82083d526ca8eee0f70b714bea11910ca7b12b8efe8acdcb3b8fc6c0519, and there's good reason to believe that this change was unintentional - there's no acknowledgement of it in the PR comments, the "Created at" filter is essentially non-functional since it filters on an exact timestamp rather than a date range, and the labels have not been changed from the verbose_name field defaults (which are somewhat confusing when used outside the context of the create/edit form).

The "Redirect to a page" filter in particular is causing issues on large sites as this dropdown can legitimately run to many thousands of entries and exceed web server resource limits.

Thus, roll back this filter set to its previous state of just `is_permanent` and `site`. If a user needs to find all redirects pointing to a given page, searching on the page title will generally be sufficient.
2024-09-19 09:56:44 +01:00
sag​e 4ec9220916 Fix content metrics plugin to work on the main element before falling back to `body` ()
Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
2024-09-19 08:54:34 +01:00
Matt Westcott 5d0bb0636f Release note for in 6.2.2 2024-09-12 19:17:23 +01:00
smark-1 15863a6aa1 Fix link to Users search in the "Other searches" bar
Regression in b6fdd8c408
2024-09-12 19:15:06 +01:00
Matt Westcott 6a42ab9b02 Release note for in 6.2.2 2024-09-11 19:48:18 +01:00
Sage Abdullah e9556b3169 Clarify UserViewSet customization to avoid confusion with the custom user model's app config 2024-09-11 19:48:18 +01:00
Matt Westcott 15d68776b8 Release note for in 6.2.2 2024-08-27 15:05:36 +01:00
Matt Westcott 4604ec8a5b Add missing |unlocalize filters 2024-08-27 15:05:17 +01:00
Matt Westcott 950104592e Add release note template for 6.2.2 2024-08-27 14:36:05 +01:00
Matt Westcott 37bc8c8cb7 Version bump to 6.2.1 2024-08-20 16:18:59 +01:00
Matt Westcott 1d4bd11612 Fill in release date for 6.2.1 2024-08-20 16:18:27 +01:00
Matt Westcott f97fe1c047 Fetch new translations from Transifex 2024-08-20 16:17:36 +01:00
Matt Westcott ab6bed2954 Release note for 2024-08-20 16:04:40 +01:00
Matt Westcott e76d04dfb2 Ensure that moderators without explicit edit permission on snippets are granted access to the ping endpoint
Fixes 
2024-08-20 16:04:40 +01:00
Matt Westcott f53be91b90 Ensure that moderators without explicit edit permission on pages are granted access to the ping endpoint 2024-08-20 16:04:40 +01:00
Matt Westcott 14a57215ed Avoid importing custom user models at load time in wagtail.admin.models
As per https://docs.djangoproject.com/en/5.0/topics/auth/customizing/#referencing-the-user-model , module-level code such as ForeignKey definitions should use `AUTH_USER_MODEL` rather than `get_user_model()`.

Probably fixes  (unconfirmed)
2024-08-15 11:09:03 +01:00
Sage Abdullah e7c7b971b2 Fix broken task type filter in workflow task chooser modal ()
Fixes 
2024-08-08 18:51:54 +01:00
Matt Westcott 1ab4f45b18 Generate new strings for translation 2024-08-07 10:10:42 +01:00
Matt Westcott 37a5e8dabc Handle `child_block` being passed as a kwarg in ListBlock.deconstruct_with_lookup ()
Fixes 
2024-08-06 14:36:17 +01:00
Matt Westcott 4a79d853ba Add release notes template for 6.2.1 2024-08-06 14:35:08 +01:00
Matt Westcott 6161b09644 Fix no-index directive for Sphinx 7.4.7 2024-08-01 14:41:30 +01:00
Matt Westcott f051c873ac Fill in release date for 6.2 2024-08-01 13:00:37 +01:00
Matt Westcott c47bea2e15 Version bump to 6.2 final 2024-08-01 12:58:48 +01:00
Matt Westcott 3d03794048 Fetch new translations from Transifex 2024-08-01 12:56:43 +01:00
smark-1 0833e7bf22 Fix typo in admin url finder docs () 2024-08-01 11:49:04 +01:00
DK bd952219b0 Fix typo in 6.2 release notes and changelog ()
Co-authored-by: Daniel Kirkham <d.kirkham@kirkham.id.au>
2024-08-01 11:49:04 +01:00
Sage Abdullah 85961c314f
Improve styles for overly long selectors in checks results 2024-07-31 12:21:13 +01:00
Thibaud Colas 1e517bac27
Disable pointer events on checker highlights to simplify DevTools inspections 2024-07-31 12:21:09 +01:00
Thibaud Colas 43ede8879b
Log accessibility checker results when present 2024-07-31 12:21:00 +01:00
Thibaud Colas 72a4884ee4
Re-instate accessibility check selectors in CMS. Fix 2024-07-31 12:20:53 +01:00
Sage Abdullah b758007587 Do not suggest using the custom user model's app config as the custom wagtail.users app config
Doing so would mean the "models" module of the app that contains the
custom user model will be used in favour of the models module of the
wagtail.users app, which contains the UserProfile model. As a result,
the UserProfile model becomes mistakenly picked up by the wagtailcore
app, creating a bogus migration when makemigrations is run.

This partially reverts the docs to the version before
449a48d7f9, in particular the paragraphs
about creating the custom AppConfig subclass for wagtail.users.
2024-07-29 17:36:10 +01:00
Matt Westcott 46c78be145 Release note for 2024-07-29 16:00:25 +01:00
Matt Westcott de2c06281c Give meaningful error when using SnippetChooserBlock on a non-snippet model
Ref  - this is identified as a common cause of AttributeErrors during StreamField block serialization.
2024-07-29 16:00:25 +01:00
Matt Westcott e20624a482 Prevent AttributeErrors thrown within StreamField block serialization from being masked
Ref . Generally, the first call to _build_block_json happens when accessing the `media` property of the widget. Django wraps this in a try/except AttributeError to guard against the widget not defining a `media` property, so if an AttributeError occurs during the `JSContext.pack` operation, the error will be suppressed and the BlockWidget left in an invalid state where `_js_context` is defined but `_block_json` is not.

Fix this by wrapping exceptions raised during `JSContext.pack` with a ValueError (which is probably less likely to be caught), and updating BlockWidget to not assume that `_js_context` being defined implies `_block_json` is defined.
2024-07-29 16:00:25 +01:00
Sage Abdullah b4ba3d635d Fix duplicated rich text input inside choosers ()
Fixes 
2024-07-29 15:09:06 +01:00
Sage Abdullah 84c9ab416b Ensure submit buttons inside dialogs also trigger the overwrite confirmation dialog 2024-07-29 08:43:41 +02:00
Sage Abdullah 9dea339727 Clarify overwrite dialog message and remove reference to model name
Change 'session' to 'window' and remove mention of model name to avoid
issues with gendered languages
2024-07-29 08:20:02 +02:00
Sage Abdullah b7dacf52ea Revert "Use the proper content type for confirmation messages"
This reverts commit 6c44d6113c.
2024-07-29 08:19:58 +02:00
Matt Westcott fe9a2c493f Use Nathanaël Jourdane's full name 2024-07-26 10:34:58 +01:00
Matt Westcott 6e1645b86d Prevent deconstruct_with_lookup from breaking on ListBlock subclasses with custom constructors
Fixes 
2024-07-25 15:29:11 +01:00
Matt Westcott 7b30436be4 Remove note about database search not ordering by relevance
This text existed since Wagtail 1.x and is referring to the original database backend that just did substring matches (which is now the fallback backend), before we supported database-backed full-text search.
2024-07-24 22:32:54 +01:00
Thibaud Colas b8d85175e4 Reorder and rewrite 6.2 release notes 2024-07-23 10:52:24 +01:00
Matt Westcott 6c11616bd6 Version bump to 6.2rc1 2024-07-19 16:52:28 +01:00
2585 zmienionych plików z 37300 dodań i 58496 usunięć
.circleci

Wyświetl plik

@ -1,7 +1,16 @@
{
"sourceType": "unambiguous",
"presets": [
"@babel/preset-env",
[
"@babel/preset-env",
{
"targets": {
"chrome": 100,
"safari": 15,
"firefox": 91
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],

Wyświetl plik

@ -3,39 +3,37 @@ version: 2
jobs:
backend:
docker:
- image: cimg/python:3.12
- image: cimg/python:3.8.11
environment:
PIPENV_VENV_IN_PROJECT: true
steps:
- checkout
- run: python --version > .python_version
- restore_cache:
key: &venv-cache venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
key: pipenv-v1-{{ checksum "setup.py" }}
# Only install if .venv wasnt cached.
- run: |
if [[ ! -e ".venv" ]]; then
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .[testing,docs]
pipenv install -e .[testing,docs]
fi
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
- save_cache:
key: *venv-cache
key: pipenv-v1-{{ checksum "setup.py" }}
paths:
- .venv
- run: ruff check .
- run: ruff format --check .
- run: semgrep --config .semgrep.yml --error .
- run: git ls-files '*.html' | xargs djhtml --check
- run: curlylint --parse-only wagtail
- run: doc8 docs
- run: pipenv run ruff check .
- run: pipenv run ruff format --check .
- run: pipenv run semgrep --config .semgrep.yml --error .
- run: git ls-files '*.html' | xargs pipenv run djhtml --check
- run: pipenv run curlylint --parse-only wagtail
- run: pipenv run doc8 docs
- run:
name: Run tests
command: |
export PYTHONUNBUFFERED=1
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1 python -u runtests.py --parallel=2
pipenv run python -u runtests.py --parallel=2
frontend:
docker:
- image: cimg/node:22.11
- image: cimg/node:20.9
steps:
- checkout
- restore_cache:
@ -64,50 +62,44 @@ jobs:
ui_tests:
docker:
- image: cimg/python:3.12-browsers
- image: cimg/python:3.8.11-browsers
environment:
PIPENV_VENV_IN_PROJECT: true
DJANGO_SETTINGS_MODULE: wagtail.test.settings_ui
DJANGO_DEBUG: 'true'
DJANGO_DEBUG: true
steps:
- checkout
- attach_workspace:
at: ~/project
- run: python --version > .python_version
- restore_cache:
key: &ui_tests-venv-cache ui_tests-venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
key: pipenv-v1-{{ checksum "setup.py" }}
# Only install if .venv wasnt cached.
- run: |
if [[ ! -e ".venv" ]]; then
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .[testing]
pipenv install -e .[testing]
fi
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
- save_cache:
key: *ui_tests-venv-cache
key: pipenv-v1-{{ checksum "setup.py" }}
paths:
- .venv
- restore_cache:
key: &ui_tests-npm-cache ui_tests-npm_integration-v3-{{ checksum "client/tests/integration/package-lock.json" }}
key: ui_tests-npm_integration-v1-{{ checksum "client/tests/integration/package-lock.json" }}
# Only install if node_modules wasnt cached.
- run: |
if [[ ! -e "client/tests/integration/node_modules" ]]; then
npm --prefix ./client/tests/integration ci
fi
- save_cache:
key: *ui_tests-npm-cache
key: ui_tests-npm_integration-v1-{{ checksum "client/tests/integration/package-lock.json" }}
paths:
- client/tests/integration/node_modules
# Also cache the global location where Puppeteer stores browsers.
# https://pptr.dev/guides/configuration/#changing-the-default-cache-directory
- ~/.cache/puppeteer
- run: ./wagtail/test/manage.py migrate
- run: pipenv run ./wagtail/test/manage.py migrate
- run:
command: ./wagtail/test/manage.py runserver 0:8000
command: pipenv run ./wagtail/test/manage.py runserver 0:8000
background: true
- run: ./wagtail/test/manage.py createcachetable
- run: pipenv run ./wagtail/test/manage.py createcachetable
- run:
command: ./wagtail/test/manage.py createsuperuser --noinput
command: pipenv run ./wagtail/test/manage.py createsuperuser --noinput
environment:
DJANGO_SUPERUSER_EMAIL: admin@example.com
DJANGO_SUPERUSER_USERNAME: admin
@ -117,23 +109,24 @@ jobs:
environment:
JEST_JUNIT_OUTPUT_DIR: reports/jest
- run:
command: ./wagtail/test/manage.py collectstatic --noinput
command: pipenv run ./wagtail/test/manage.py collectstatic --noinput
environment:
DJANGO_DEBUG: 'false'
DJANGO_DEBUG: false
STATICFILES_STORAGE: manifest
- store_test_results:
path: ./reports/jest
nightly-build:
docker:
- image: cimg/python:3.12-node
- image: cimg/python:3.8.11-node
steps:
- checkout
- run: pip install --user build boto3
- run: pip install --user wheel boto3
- run: npm install
- run: npm run build
- run: PYTHONPATH=. python scripts/nightly/get_version.py > __init__.py
- run: mv __init__.py wagtail/__init__.py
- run: python -m build
- run: python setup.py bdist_wheel
- run: python scripts/nightly/upload.py
workflows:

Wyświetl plik

@ -11,6 +11,7 @@ wagtail/images/static
wagtail/embeds/static
wagtail/search/static
wagtail/snippets/static
wagtail/users/static
wagtail/contrib/*/static
.mypy_cache
/storybook-static

Wyświetl plik

@ -132,14 +132,14 @@ module.exports = {
files: [
'client/extract-translatable-strings.js',
'client/tests/**',
'tailwind.config.js',
'webpack.config.js',
'*.stories.js',
'*.stories.tsx',
'*.test.js',
'tailwind.config.js',
'storybook/**/*',
'*.test.ts',
'*.test.tsx',
'**/storybook/**',
'*.test.js',
'*.stories.js',
'*.stories.tsx',
],
rules: {
'@typescript-eslint/no-empty-function': 'off',
@ -167,6 +167,7 @@ module.exports = {
'wagtail/images/static_src/wagtailimages/js/add-multiple.js',
'wagtail/images/static_src/wagtailimages/js/focal-point-chooser.js',
'wagtail/images/static_src/wagtailimages/js/image-url-generator.js',
'wagtail/users/static_src/wagtailusers/js/group-form.js',
],
globals: { $: 'readonly', jQuery: 'readonly' },
},
@ -174,6 +175,7 @@ module.exports = {
{
files: ['wagtail/**/**'],
globals: {
buildExpandingFormset: 'readonly',
escapeHtml: 'readonly',
ModalWorkflow: 'readonly',
DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS: 'writable',

2
.gitattributes vendored
Wyświetl plik

@ -1,2 +0,0 @@
# Make GitHub highlight html files as Django templates
*.html linguist-language=django

Wyświetl plik

@ -1,4 +1,4 @@
# Contributing
# Contributing to Wagtail
Thank you for considering to help Wagtail.

Wyświetl plik

@ -24,9 +24,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1

Wyświetl plik

@ -13,25 +13,24 @@ concurrency:
cancel-in-progress: true
# Our test suite should cover:
# - all supported databases against current Python and Django (including psycopg v2 and v3)
# - all supported databases against current Python and Django
# - at least one test run for each older supported version of Python and Django
# - at least one test run for each supported Elasticsearch version
# - a test run against Django's git main and active stable branch (allowing failures)
# - test runs with USE_EMAIL_USER_MODEL=yes, DISABLE_TIMEZONE=yes and WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
# - test runs with USE_EMAIL_USER_MODEL=yes and DISABLE_TIMEZONE=yes
# Current configuration:
# - django 4.2, python 3.9, postgres:12, psycopg 2, parallel
# - django 4.2, python 3.10, mysql:8.0
# - django 4.2, python 3.11, mariadb:10.5
# - django 5.1, python 3.12, mysql:8.4, USE_EMAIL_USER_MODEL=yes
# - django 5.1, python 3.12, mariadb:11.4, USE_EMAIL_USER_MODEL=yes
# - django 5.2, python 3.13, sqlite, parallel, WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
# - django 5.2, python 3.13, postgres:15, psycopg 3, parallel, DISABLE_TIMEZONE=yes
# - django stable/5.2.x, python 3.12, postgres:15, psycopg 3 (allow failures)
# - django main, python 3.13, postgres:latest, psycopg 3, parallel (allow failures)
# - elasticsearch 7, django 4.2, python 3.9, postgres:latest, psycopg 2
# - opensearch 2, django 5.2, python 3.10, sqlite
# - elasticsearch 8, django 5.1, python 3.13, sqlite, USE_EMAIL_USER_MODEL=yes
# - django 4.2, python 3.8, postgres:12, parallel
# - django 4.2, python 3.9, mysql:8.0
# - django 4.2, python 3.10, sqlite
# - django 5.0, python 3.12, mysql:8.1, parallel
# - django 5.0, python 3.11, postgres:12, parallel, USE_EMAIL_USER_MODEL=yes
# - django 5.0, python 3.12, postgres:15, parallel, DISABLE_TIMEZONE=yes
# - django stable/5.1.x, python 3.11, postgres:15 (allow failures)
# - django main, python 3.12, postgres:latest, parallel (allow failures)
# - elasticsearch 7, django 4.2, python 3.8, postgres:latest
# - opensearch 2, django 4.2, python 3.9, sqlite
# - elasticsearch 8, django 5.0, python 3.11, sqlite, USE_EMAIL_USER_MODEL=yes
# Some tests are run in parallel by passing --parallel to runtests.py.
# When running tests in parallel, some errors cannot be pickled and result in
@ -48,17 +47,13 @@ jobs:
strategy:
matrix:
include:
- python: '3.13'
django: 'Django>=5.2,<5.3'
check_template_number_format: '1'
parallel: '--parallel'
- python: '3.10'
django: 'Django>=4.2,<4.3'
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
@ -70,17 +65,14 @@ jobs:
- name: Test
run: |
WAGTAIL_FAIL_ON_VERSIONED_STATIC=1 DJANGO_SETTINGS_MODULE=wagtail.test.settings django-admin check
coverage run --parallel-mode --source wagtail runtests.py ${{ matrix.parallel }}
coverage run --parallel-mode --source wagtail runtests.py
env:
DATABASE_ENGINE: django.db.backends.sqlite3
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT: ${{ matrix.check_template_number_format }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
test-postgres:
runs-on: ubuntu-latest
@ -88,32 +80,30 @@ jobs:
strategy:
matrix:
include:
- python: '3.9'
- python: '3.8'
django: 'Django>=4.2,<4.3'
psycopg: 'psycopg2>=2.6'
experimental: false
parallel: '--parallel'
- python: '3.13'
django: 'Django>=5.2,<5.3'
psycopg: 'psycopg>=3.1.8'
- python: '3.11'
django: 'Django>=5.0,<5.1'
experimental: false
emailuser: emailuser
parallel: '--parallel'
- python: '3.12'
django: 'Django>=5.0,<5.1'
postgres: 'postgres:15'
notz: notz
experimental: false
parallel: '--parallel'
- python: '3.12'
django: 'git+https://github.com/django/django.git@stable/5.2.x#egg=Django'
psycopg: 'psycopg>=3.1.8'
- python: '3.11'
django: 'git+https://github.com/django/django.git@stable/5.1.x#egg=Django'
postgres: 'postgres:15'
experimental: true
- python: '3.13'
- python: '3.12'
django: 'git+https://github.com/django/django.git@main#egg=Django'
psycopg: 'psycopg>=3.1.8'
experimental: true
postgres: 'postgres:latest'
parallel: '--parallel'
install_extras: |
pip uninstall -y django-modelcluster
pip install "git+https://github.com/wagtail/django-modelcluster.git@main#egg=django-modelcluster"
services:
postgres:
image: ${{ matrix.postgres || 'postgres:12' }}
@ -124,18 +114,16 @@ jobs:
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "${{ matrix.psycopg }}"
pip install "psycopg2>=2.6"
pip install -e '.[testing]' --config-settings editable_mode=strict
pip install "${{ matrix.django }}"
${{ matrix.install_extras }}
@ -151,29 +139,10 @@ jobs:
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
DISABLE_TIMEZONE: ${{ matrix.notz }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
- name: Test project template
if: ${{ matrix.experimental }}
env:
PYTHONWARNINGS: error
run: |
wagtail start testproject
cd testproject
tee -a testproject/settings/local.py << EOF
from warnings import filterwarnings
SILENCED_SYSTEM_CHECKS = ["wagtailadmin.W001"]
# Remove when https://github.com/wagtail/Willow/issues/166 is resolved
filterwarnings(
"ignore", "The AVIF support in this library is marked as deprecated"
)
EOF
python manage.py makemigrations --check --dry-run
python manage.py migrate
python manage.py check --fail-level WARNING
test-mysql:
runs-on: ubuntu-latest
@ -181,42 +150,28 @@ jobs:
strategy:
matrix:
include:
- python: '3.10'
- python: '3.9'
django: 'Django>=4.2,<4.3'
experimental: false
- python: '3.11'
django: 'Django>=4.2,<4.3'
experimental: false
mysql: 'mariadb:10.5'
- python: '3.12'
django: 'Django>=5.1,<5.2'
django: 'Django>=5.0,<5.1'
experimental: false
mysql: 'mariadb:11.4'
emailuser: emailuser
- python: '3.12'
django: 'Django>=5.1,<5.2'
experimental: false
mysql: 'mysql:8.4'
emailuser: emailuser
parallel: '--parallel'
mysql: 'mysql:8.1'
services:
mysql:
image: ${{ matrix.mysql || 'mysql:8.0' }}
env:
MARIADB_ROOT_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: wagtail
HEALTH_CMD: ${{ startsWith(matrix.mysql, 'mariadb') && 'healthcheck.sh --connect --innodb_initialized' || 'mysqladmin --protocol=tcp ping' }}
ports:
- 3306:3306
options: --health-cmd=$HEALTH_CMD --health-interval=10s --health-timeout=5s --health-retries=3 --cap-add=sys_nice
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 --cap-add=sys_nice
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
@ -234,23 +189,19 @@ jobs:
DATABASE_ENGINE: django.db.backends.mysql
DATABASE_HOST: '127.0.0.1'
DATABASE_USER: root
DATABASE_PASSWORD: root
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
DISABLE_TIMEZONE: ${{ matrix.notz }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
test-sqlite-elasticsearch8:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- python: '3.13'
django: 'Django>=5.2,<5.3'
- python: '3.11'
django: 'Django>=5.0,<5.1'
emailuser: emailuser
steps:
- name: Configure sysctl limits
@ -259,7 +210,7 @@ jobs:
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- uses: getong/elasticsearch-action@v1.3
- uses: getong/elasticsearch-action@v1.2
with:
elasticsearch version: 8.8.0
host port: 9200
@ -267,11 +218,9 @@ jobs:
host node port: 9300
node port: 9300
discovery type: 'single-node'
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
@ -289,11 +238,10 @@ jobs:
DATABASE_ENGINE: django.db.backends.sqlite3
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
test-postgres-elasticsearch7:
runs-on: ubuntu-latest
@ -301,7 +249,7 @@ jobs:
strategy:
matrix:
include:
- python: '3.9'
- python: '3.8'
django: 'Django>=4.2,<4.3'
experimental: false
@ -324,12 +272,9 @@ jobs:
- uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.6.1
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
@ -351,11 +296,10 @@ jobs:
DATABASE_PASSWORD: postgres
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
test-sqlite-opensearch2:
runs-on: ubuntu-latest
@ -363,8 +307,8 @@ jobs:
strategy:
matrix:
include:
- python: '3.10'
django: 'Django>=5.1,<5.2'
- python: '3.9'
django: 'Django>=4.2,<4.3'
experimental: false
steps:
@ -377,11 +321,9 @@ jobs:
- uses: ankane/setup-opensearch@v1
with:
opensearch-version: 2
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
cache: 'pip'
@ -399,11 +341,10 @@ jobs:
DATABASE_ENGINE: django.db.backends.sqlite3
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
- name: Upload coverage data
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
name: coverage-data
path: .coverage.*
include-hidden-files: true
coverage:
needs:
@ -416,12 +357,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
persist-credentials: false
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v4
with:
python-version: '3.10'
@ -431,10 +370,9 @@ jobs:
pip install coverage
- name: Download coverage data
uses: actions/download-artifact@v4
uses: actions/download-artifact@v3
with:
pattern: coverage-data-*
merge-multiple: true
name: coverage-data
- name: Combine coverage data
run: |
@ -446,14 +384,12 @@ jobs:
coverage html --skip-covered --skip-empty
- name: Upload HTML report as artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage_html_report
include-hidden-files: true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
flags: backend
token: ${{ secrets.CODECOV_TOKEN }}

1
.gitignore vendored
Wyświetl plik

@ -18,7 +18,6 @@ npm-debug.log*
/.cache/
/.pytest_cache/
/storybook-static
/wagtail/tests/test-media/
### JetBrains
.idea/

2
.nvmrc
Wyświetl plik

@ -1 +1 @@
22
20

Wyświetl plik

@ -3,7 +3,7 @@ default_language_version:
python: python3
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.9.6'
rev: 'v0.1.5'
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]

Wyświetl plik

@ -9,11 +9,5 @@ python:
path: .
extra_requirements:
- docs
formats: all
sphinx:
configuration: docs/conf.py
fail_on_warning: True
search:
ranking:
releases/*: -1
releases/upgrading.html: 0

Wyświetl plik

@ -39,9 +39,6 @@ rules:
- metavariable-regex:
metavariable: $STRING_ID
regex: ".*%\\w.*"
paths:
exclude:
- 'wagtail/test/numberformat.py'
message: >
Do not use anonymous placeholders for translations.
Use printf style formatting with named placeholders instead.

Wyświetl plik

@ -3,7 +3,7 @@ deployments:
dockerimage: python:3.11.4-slim-bullseye
build_steps:
- apt-get update && apt-get install -y libssl-dev libpq-dev git build-essential libfontconfig1 libfontconfig1-dev curl
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_22.x | bash -"
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_20.x | bash -"
- apt install -y nodejs
- pip install setuptools pip --upgrade --force-reinstall
- cd /code

Wyświetl plik

@ -23,7 +23,12 @@ module.exports = {
// Would be valuable for strict BEM components but is too hard to enforce with legacy code.
'no-descending-specificity': null,
// Refined ordering to align with media mixin usage - see https://github.com/wagtail/stylelint-config-wagtail/issues/37
'order/order': ['dollar-variables', 'custom-properties', 'declarations'],
'order/order': [
'dollar-variables',
'custom-properties',
{ type: 'at-rule', hasBlock: false }, // @-rules that have no nesting.
'declarations',
],
// Some parts of declaration-strict-value commented out until we are in a position to enforce them.
'scale-unlimited/declaration-strict-value': [
[
@ -51,7 +56,6 @@ module.exports = {
'none',
'unset',
'transparent',
'normal',
// System colors for forced-colors styling.
// See https://drafts.csswg.org/css-color-4/#css-system-colors.
'Canvas',

Wyświetl plik

@ -1,369 +1,6 @@
Changelog
=========
7.0 LTS (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~~~~~
* Add formal support for Django 5.2 (Matt Westcott)
* Allow validation of required fields to be deferred on saving drafts (Matt Westcott, Sage Abdullah)
* Add `WAGTAIL_` prefix to Wagtail-specific tag settings (Aayushman Singh)
* Implement `normalize` on `TypedTableBlock` to assist with setting `default` and `preview_value` (Sage Abdullah)
* Apply normalization when modifying a `StreamBlock`'s value to assist with programmatic changes to `StreamField` (Matt Westcott)
* Allow a custom image rendition model to define its unique constraint with `models.UniqueConstraint` instead of `unique_together` (Oliver Parker, Cynthia Kiser, Sage Abdullah)
* Default to the `standard` tokenizer on Elasticsearch, to correctly handle numbers as tokens (Matt Westcott)
* Add color-scheme meta tag to Wagtail admin (Ashish Nagmoti)
* Add the ability to set the default privacy restriction for new pages using `get_default_privacy_setting` (Shlomo Markowitz)
* Improve performance of batch purging page urls in the frontend cache, avoiding n+1 query issues (Andy Babic)
* Add better support and documentation for overriding or extending icons used in the in the userbar (Sébastien Corbin)
* List the comments action, if comments are enabled, within the admin keyboard shortcuts dialog (Dhruvi Patel)
* Add better support and documentation for overriding the default field widgets used within form pages (Baptiste Mispelon)
* Allow workflow tasks to specify a template for the action modal via `get_template_for_action` (Sage Abdullah)
* Change 'Publish' button label to 'Schedule to publish' if go-live schedule is set (Sage Abdullah)
* Exclude snippets that have their own menu items from the "Snippets" menu (Andy Chosak, Matt Westcott)
* Fix: Take preferred language into account for translatable strings in client-side code (Bernhard Bliem, Sage Abdullah)
* Fix: Do not show the content type column as sortable when searching pages (Srishti Jaiswal, Sage Abdullah)
* Fix: Support simple subqueries for `in` and `exact` lookup on Elasticsearch (Sage Abdullah)
* Fix: Force preview panel scroll behavior to instant to avoid flickering (Sage Abdullah)
* Fix: Support translating with the preferred language for rich text formatting labels (Bernhard Bliem, Sage Abdullah)
* Fix: Make "Actions" label translatable within the rich text toolbar (Bernhard Bliem, Sage Abdullah)
* Fix: Fix incorrect "Views (past week)" heading on promoted search results listing (Baptiste Mispelon)
* Fix: Ensure `InlinePanel` will be correctly ordered after the first save when `min_num` is used (Elhussein Almasri, Joel William)
* Fix: Avoid deprecation warnings about URLField `assume_scheme` on Django 5.x (Sage Abdullah)
* Fix: Fix setup.cfg syntax for setuptools v78 (Sage Abdullah)
* Fix: Ensure `ImproperlyConfigured` is thrown from `db_field` on unbound `FieldPanel`s as intended (Matt Westcott)
* Fix: Refine the positioning of the add comment button next to select, radio, checkbox fields and between field row columns (Srishti Jaiswal)
* Fix: Show the correct privacy status for child collections of private collections (Shlomo Markowitz)
* Fix: Ensure reference index correctly handles models with primary keys not named `id` (Sage Abdullah)
* Fix: On "move page" bulk action, do not prefill the destination with the root page (Stefan Hammer)
* Docs: Add missing `django.contrib.admin` to list of apps in "add to Django project" guide (Mohamed Rabiaa)
* Docs: Add tutorial on deploying on Ubuntu to third-party tutorials (Mohammad Fathi Rahman)
* Docs: Document that request_or_site is optional on BaseGenericSetting.load (Matt Westcott)
* Docs: Mention third-party StreamField based form builder packages in the form builder documentation (Matt Westcott)
* Docs: Clarify that `insert_editor_js` hook applies to all core editing/creation views (LB (Ben) Johnston)
* Docs: Clarify requirement for non-page models using model mixins to be registered as snippets (Sage Abdullah)
* Maintenance: Migrate away from deprecated Sass import rules to module system (Srishti Jaiswal)
* Maintenance: Apply Sass mixed declarations migration in preparation for CSS nesting (Prabhpreet Kaur)
* Maintenance: Refactor styles for Draftail, minimap, and comments to fix remaining Sass migration warnings (Thibaud Colas)
* Maintenance: npm package updates; `downshift`, `focus-trap-react`, `immer`, `redux`, `uuid` (LB (Ben) Johnston)
* Maintenance: Validate against invalid characters in Lexeme values (Matt Westcott)
* Maintenance: Split up `wagtail.models` module into submodules (Matt Westcott)
* Maintenance: Update `ruff` to 0.9.6 (Sage Abdullah)
* Maintenance: Fix up `stubs` & `adapter` contents to better support Jest testing (LB (Ben) Johnston)
* Maintenance: Cleanup Stimulus controller imports, JSDoc & linting (LB (Ben) Johnston)
* Maintenance: Rename `SkipLinkController` to `FocusController` with improved reusability, updated unit tests, and added story (LB (Ben) Johnston)
* Maintenance: Fix CI testing issues with the Stimulus `LocaleController` time zones & non-deterministic page ordering tests (Sage Abdullah)
* Maintenance: Make GitHub highlight `.html` files as Django templates (Jake Howard)
* Maintenance: Remove admin JavaScript imports from shared template includes, moving the imports to the appropriate core admin inclusion locations (Sai Srikar Dumpeti)
* Maintenance: Remove non-editing view inclusions of the `insert_editor_js` hook output, deprecate the wrapper template tag `_editor_js.html` (Sai Srikar Dumpeti, LB (Ben) Johnston)
* Maintenance: Remove upper bound on Django dependency (Matt Westcott)
* Maintenance: Add `default_auto_field` setting to home app in project template (Sylvain Boissel)
* Maintenance: Migrate setuptools configuration from `setup.py` and `setup.cfg` to `pyproject.toml` (Sage Abdullah)
* Maintenance: Refactor `move_choose_destination` to a class-based view (Chiemezuo Akujobi)
* Maintenance: Remove deprecated `wagtailadmin/shared/ajax_pagination_nav.html` template (Sage Abdullah)
* Maintenance: Formally deprecate support for listing views with no breadcrumbs (Sage Abdullah)
6.4.2 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~~~
* Fix: Do not show upgrade notification if the installed version is the latest (Sage Abdullah)
6.4.1 (21.02.2025)
~~~~~~~~~~~~~~~~~~
* Fix: Prevent error when filtering by locale and searching with Elasticsearch (Sage Abdullah)
* Fix: Support searching `none()` querysets (Matt Westcott)
* Fix: Correctly handle UUID primary keys when invoking background tasks (Matt Westcott)
* Fix: Fix regression where nested sub-menu items would not be visible (Sage Abdullah)
* Fix: Ensure the top of the minimap correctly adjusts when resizing the browser viewport (Thibaud Colas)
* Fix: Remove obsolete SubqueryConstraint check in search backends, for provisional Django 5.2 compatibility (Sage Abdullah)
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
* Docs: Fix typo in the headless documentation page (Mahmoud Nasser)
* Docs: Fix typo in `Page.get_route_paths` docstring (Baptiste Mispelon)
* Docs: Upgrade sphinx-wagtail-theme to v6.5.0 (Sage Abdullah)
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
* Maintenance: Relax upper version boundaries for django-taggit and beautifulsoup4 (Matt Westcott)
6.4 (03.02.2025)
~~~~~~~~~~~~~~~~
* Support for background tasks using `django-tasks` (Jake Howard)
* Add search terms report (Noah van der Meer, Sage Abdullah)
* Add the ability to apply basic Page QuerySet optimizations to `specific()` sub-queries using `select_related` & `prefetch_related` (Andy Babic)
* Increase `DATA_UPLOAD_MAX_NUMBER_FIELDS` in project template (Matt Westcott)
* Stop invalid Site hostname records from breaking preview (Matt Westcott)
* Set sensible defaults for InlinePanel heading and label (Matt Westcott)
* Limit tags autocompletion to 10 items and add delay to avoid performance issues with large number of matching tags (Aayushman Singh)
* Add the ability to restrict what types of requests a Pages supports via `allowed_http_methods` (Andy Babic)
* Allow plain strings in panel definitions as shorthand for `FieldPanel` / `InlinePanel` (Matt Westcott)
* Only allow selection of valid new parents within the copy Page view (Mauro Soche)
* Add `on_serve_page` hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)
* Add support for `WAGTAIL_GRAVATAR_PROVIDER_URL` URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)
* Add `get_avatar_url` hook to customise user avatars (James Harrington)
* Set content security policy (CSP) headers to block embedded content when serving images and documents (Jake Howard, with thanks to Ali İltizar for the initial report)
* Add `page` as a third parameter to the `construct_wagtail_userbar` hook (claudobahn)
* Enable breadcrumbs in revisions compare view (Sage Abdullah)
* Skip loading of unused JavaScript to speed up 404 page rendering (Sage Abdullah)
* Replace l18n library with JavaScript Intl API for time zone options in Account view (Sage Abdullah)
* Use explicit label for defaulting to server language in account settings (Sage Abdullah)
* Add support for specifying an operator on `Fuzzy` queries (Tom Usher)
* Remove support for Safari 15 (Thibaud Colas)
* Populate the ImageBlock alt text from the images default alt text when selecting a new image (Matt Westcott)
* Prevent main menu from re-rendering when clicking outside while the menu is closed (Sage Abdullah)
* Fill in the ImageBlock alt text from the images default alt text when converting from ImageChooserBlock (Cynthia Kiser)
* Make sure typing text at the bottom of the page editor always scrolls enough to keep the text into view (Jatin Bhardwaj)
* Add StreamField and InlinePanel interfaces support for drag-and-drop reordering of items (Thibaud Colas, Sage Abdullah)
* Add previews support for StreamField blocks inside the block picker (Sage Abdullah, Thibaud Colas)
* Fix: Improve handling of translations for bulk page action confirmation messages (Matt Westcott)
* Fix: Ensure custom rich text feature icons are correctly handled when provided as a list of SVG paths (Temidayo Azeez, Joel William, LB (Ben) Johnston)
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
* Fix: Fix sub-menus within the main menu cannot be closed on mobile (Bojan Mihelac)
* Fix: Fix animation overflow transition when navigating through subpages in the sidebar page explorer (manu)
* Fix: Ensure form builder supports custom admin form validation (John-Scott Atlakson, LB (Ben) Johnston)
* Fix: Ensure form builder correctly checks for duplicate field names when using a custom related name (John-Scott Atlakson, LB (Ben) Johnston)
* Fix: Normalize `StreamField.get_default()` to prevent creation forms from breaking (Matt Westcott)
* Fix: Prevent out-of-order migrations from skipping creation of image/document choose permissions (Matt Westcott)
* Fix: Use correct connections on multi-database setups in database search backends (Jake Howard)
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
* Fix: Show the correct privacy status in the sidebar when creating a new page (Joel William)
* Fix: Prevent generic model edit view from unquoting non-integer primary keys multiple times (Matt Westcott)
* Fix: Ensure comments are functional when editing Page models with `read_only` `Fieldpanel`s in use (Strapchay)
* Fix: Ensure the accessible labels and tooltips reflect the correct private/public status on the live link button within pages after changing the privacy (Ayaan Qadri)
* Fix: Fix empty `th` (table heading) elements that are not compliant with accessibility standards (Jai Vignesh J)
* Fix: Ensure `MultipleChooserPanel` using images or documents work when nested within an `InlinePanel` when no other choosers are in use within the model (Elhussein Almasri)
* Fix: Ensure `MultipleChooserPanel` works after doing a search in the page chooser modal (Matt Westcott)
* Fix: Ensure new `ListBlock` instances get created with unique IDs in the admin client for accessibility and mini-map element references (Srishti Jaiswal)
* Fix: Return never-cache HTTP headers when serving pages and documents with view restrictions (Krystian Magdziarz, Dawid Bugajewski)
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
* Fix: Add `aria-expanded` attribute to new column button on `TypedTableBlock` to reflect menu state (Ayaan Qadri, Scott Cranfill)
* Fix: Allow page models to extend base `Page` panel definitions without importing `wagtail.admin` (Matt Westcott)
* Fix: Fix crash when loading the dashboard with only the "unlock" or "bulk delete" page permissions (Unyime Emmanuel Udoh, Sage Abdullah)
* Fix: Improve deprecation warning for `WidgetWithScript` by raising it with `stacklevel=3` (Joren Hammudoglu)
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
* Fix: Add missing heading and breadcrumbs in Account view (Sage Abdullah)
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
* Fix: Prevent redundant calls to `Site.find_for_request()` from `Page.get_url_parts()` (Andy Babic)
* Fix: Prevent error on listings when searching and filtering by locale (Matt Westcott, Sage Abdullah)
* Fix: Add missing space in panels check warning message (Stéphane Blondon)
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
* Docs: Move the model reference page from reference/pages to the references section as it covers all Wagtail core models (Srishti Jaiswal)
* Docs: Move the panels reference page from references/pages to the references section as panels are available for any model editing, merge panels API into this page (Srishti Jaiswal)
* Docs: Move the tags documentation to standalone advanced topic, instead of being inside the reference/pages section (Srishti Jaiswal)
* Docs: Refine the adding reports page so that common (page/non-page) class references are at the top and the full page only example has correct heading nesting (Alessandro Chitarrini)
* Docs: Add the `wagtail start` command to the management commands reference page (Damilola Oladele)
* Docs: Refine the project template page sections and document common issues encountered when creating custom templates (Damilola Oladele)
* Docs: Refine titles, references and URLS to better align with the documentation style guide, including US spelling (Srishti Jaiswal)
* Docs: Recommend a larger `DATA_UPLOAD_MAX_NUMBER_FIELDS` when integrating Wagtail into Django (Matt Westcott)
* Docs: Improve code highlighting and formatting for Python docstrings in core models (Srishti Jaiswal)
* Docs: Update all JavaScript inline scripts & some CSS inline style tags to a CSP compliant approach by using external scripts/styles (Aayushman Singh)
* Docs: Update usage of `mark_safe` to `format_html` for any script inclusions, to better avoid XSS issues from example code (Aayushman Singh)
* Docs: Update documentation writing guidelines to encourage better considerations of security, accessibility and good practice when writing code examples (Aayushman Singh, LB (Ben) Johnston)
* Docs: Update documentation guidelines on writing links and API reference (Sage Abdullah)
* Docs: Replace absolute URLs with intersphinx links where possible to avoid broken links (Sage Abdullah)
* Docs: Update upgrading guide and release process to better reflect the current practices (Sage Abdullah)
* Docs: Document usage of custom validation for admin form pages when using `AbstractEmailForm` or `AbstractForm` pages (John-Scott Atlakson, LB (Ben) Johnston)
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
* Docs: Fix link to `HTTPMethod` in `Page.handle_options_request()` docs (Sage Abdullah)
* Docs: Improve the Pages Theory page with added & more consistent section headings and admonitions to aid in readability (Clifford Gama)
* Docs: Fix non-functional link to the community guidelines in the Your first contribution page (Ankit Kumar)
* Docs: Introduce tags and filters by name in "Writing templates" docs (Clifford Gama)
* Docs: Add a new headless section to the documentation, incorporating parts of the 'are we headless' website content (Sævar Öfjörð Magnússon, Alex Fulcher)
* Docs: Fix Django HTML syntax formatting issue on the documents overview page (LB (Ben) Johnston)
* Docs: Separate virtual environment creation and activation steps in tutorial (Ankit Kumar)
* Docs: Update tutorial to use plain strings in place of `FieldPanel` / `InlinePanel` where appropriate (Unyime Emmanuel Udoh)
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
* Docs: Document `get_template` method on StreamField blocks (Matt Westcott)
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
* Maintenance: Close open files when reading within utils/setup.py (Ataf Fazledin Ahamed)
* Maintenance: Avoid redundant `ALLOWED_HOSTS` check in `Site.find_for_request` (Jake Howard)
* Maintenance: Update `CloneController` to ensure that `added`/`cleared` events are not dispatched as cancelable (LB (Ben) Johnston)
* Maintenance: Remove unused `uuid` UMD module as all code is now using the NPM module (LB (Ben) Johnston)
* Maintenance: Clean up JS comments throughout codebase to be aligned to JSDoc where practical (LB (Ben) Johnston)
* Maintenance: Replace `eslint-disable no-undef` linter directives with `global` comments (LB (Ben) Johnston)
* Maintenance: Upgrade Node tooling to active LTS version 22 (LB (Ben) Johnston)
* Maintenance: Remove defunct oEmbed providers (Rahul Samant)
* Maintenance: Remove obsolete non-upsert-based code for Postgres search indexing (Jake Howard)
* Maintenance: Remove unused Rangy JS library (LB (Ben) Johnston)
* Maintenance: Update `PreviewController` usage to leverage Stimulus actions instead of calling `preventDefault` manually (Ayaan Qadri)
* Maintenance: Various performance optimizations to page publishing (Jake Howard)
* Maintenance: Remove unnecessary DOM canvas.toBlob polyfill (LB (Ben) Johnston)
* Maintenance: Ensure Storybook core files are correctly running through Eslint (LB (Ben) Johnston)
* Maintenance: Add a new Stimulus `ZoneController` (`w-zone`) to support dynamic class name changes & event handling on container elements (Ayaan Qadri)
* Maintenance: Migrate jQuery class toggling & drag/drop event handling within the multiple upload views to the Stimulus ZoneController usage (Ayaan Qadri)
* Maintenance: Test project template for warnings when run against Django pre-release versions (Sage Abdullah)
* Maintenance: Refactor redirects create/delete views to use generic views (Sage Abdullah)
* Maintenance: Add JSDoc description, adopt linting recommendations, and add more unit tests for `ModalWorkflow` (LB (Ben) Johnston)
* Maintenance: Add support for for a `delay` value in `TagController` to debounce async autocomplete tag fetch requests (Aayushman Singh)
* Maintenance: Add unit tests, Storybook stories & JSDoc items for the Stimulus `DrilldownController` (Srishti Jaiswal)
* Maintenance: Enhance sidebar preview performance by eliminating duplicate asset loads on preview error (Sage Abdullah)
* Maintenance: Remove unused `LinkController` (`w-link`) (Sage Abdullah)
* Maintenance: Refactor settings `EditView` to make better use of generic `EditView` (Sage Abdullah)
* Maintenance: Add a new Stimulus `RulesController` (`w-rules`) to support declarative conditional field enabling from other field values in a form (LB (Ben) Johnston)
* Maintenance: Migrate the conditional enabling of fields in the image URL builder view away from ad-hoc jQuery to use the `RulesController` (`w-rules`) approach (LB (Ben) Johnston)
* Maintenance: Enhance the Stimulus `ZoneController` (`w-zone`) to support inactive class and a mechanism to switch the mode based on data within events (Ayaan Qadri)
* Maintenance: Use the Stimulus `ZoneController` (`w-zone`) to remove ad-hoc jQuery for the privacy switch when toggling visibility of private/public elements (Ayaan Qadri)
* Maintenance: Remove unused `is_active` & `active_menu_items` from `wagtail.admin.menu.MenuItem` (Srishti Jaiswal)
* Maintenance: Only call `openpyxl` at runtime to improve performance for projects that do not use `ReportView`, `SpreadsheetExportMixin` and `wagtail.contrib.redirects` (Sébastien Corbin)
* Maintenance: Adopt the update value `mp` instead of `mm` for 'mystery person' as the default Gravatar if no avatar found (Harsh Dange)
* Maintenance: Refactor search promotions views to use generic views and templates (Sage Abdullah, Rohit Sharma)
* Maintenance: Use built-in `venv` instead of `pipenv` in CircleCI (Sage Abdullah)
* Maintenance: Add a new Stimulus `FormsetController` (`w-formset`) to support dynamic formset insertion/deletion behavior (LB (Ben) Johnston)
* Maintenance: Enable breadcrumbs by default on admin views using generic templates (Sage Abdullah)
* Maintenance: Refactor pages `revisions_revert` view to be a subclass of `EditView` (Sage Abdullah)
* Maintenance: Move images and documents `get_usage().count()` call to view code (Sage Abdullah)
* Maintenance: Upgrade sass-loader to resolve Sass deprecation warnings (Ayaan Qadri)
6.3.4 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~~~
* Added support for Django 5.2
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
6.3.3 (03.02.2025)
~~~~~~~~~~~~~~~~~~
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
6.3.2 (02.01.2025)
~~~~~~~~~~~~~~~~~~
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
* Fix: Ensure Draftail features wrap when a large amount of features are added (Bart Cieliński)
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
6.3.1 (19.11.2024)
~~~~~~~~~~~~~~~~~~
* Fix: Restore ability to upload profile picture through account settings (Sage Abdullah)
* Fix: Correctly handle `ImageChooserBlock` to `ImageBlock` data conversions where all inputs to `bulk_to_python` are null (Storm Heg, Matt Westcott)
* Fix: Improve spacing of page / collection permissions table in Group settings (Sage Abdullah)
* Fix: Remove forced capitalization of site name on admin dashboard (Thibaud Colas)
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
* Docs: Lower search result ranking for release notes on readthedocs search (Sage Abdullah)
6.3 LTS (01.11.2024)
~~~~~~~~~~~~~~~~~~~~
* Add support for Python 3.13 (Matt Westcott)
* Add formal support for Django 5.1 (Matt Westcott)
* Add `ImageBlock` with alt text support (Chiemezuo Akujobi for Google Summer of Code, mentored by Storm Heg, Saptak Sengupta, Thibaud Colas and Matt Westcott)
* Implement incremental dashboard design enhancements (Albina Starykova, Ben Enright)
* Add a new enhanced contrast admin theming option for the admin interface (Albina Starykova, Victoria Ottah)
* Migrate workflow history views to universal listings (Sage Abdullah)
* Refactor documents views to use universal designs (Sage Abdullah)
* Refactor images views to use universal designs (Sage Abdullah)
* Implement universal listings for workflow usage and page type usage views (Sage Abdullah)
* Add search and filters to form pages listing (Sage Abdullah)
* Add support for uploading HEIC / HEIF images (Matt Westcott)
* Allow customization of preview device sizes in the live preview panel (Bart Cieliński, alexkiro, Sage Abdullah)
* Formalize support for MariaDB (Sage Abdullah, Daniel Black)
* Redirect to the last viewed listing page after deleting form submissions (Matthias Brück)
* Provide `getTextLabel` method on date / time StreamField blocks (Vaughn Dickson)
* Purge frontend cache when modifying redirects (Jake Howard)
* Deprecate the `WAGTAIL_AUTO_UPDATE_PREVIEW` setting, use `WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0` instead (Sage Abdullah)
* Consistently use `capfirst` for title-casing model verbose names (Sébastien Corbin)
* Fire `copy_for_translation_done` signal when copying translatable models as well as pages (Coen van der Kamp)
* Add support for an image `description` field across all images, to better support accessible image descriptions (Chiemezuo Akujobi)
* Prompt the user about unsaved changes when editing snippets (Sage Abdullah)
* Make dashboard upgrade banners dismissible (Sage Abdullah)
* Add support for specifying different preview modes to the "View draft" URL for pages (Robin Varghese)
* Implement new designs for the footer actions dropdown with more contrast and larger text (Sage Abdullah)
* All create/edit admin forms now use a sticky submit button, for consistency and to speed up edits (Sage Abdullah)
* Secondary form actions such as "Delete" are now in the header actions menu (Sage Abdullah)
* Allow setting page privacy rules when a restriction already exists on an ancestor page (Bojan Mihelac)
* Automatically create links when pasting content that contain URLs into a rich text input (Thibaud Colas)
* Add Uyghur language support
* Fix: Prevent page type business rules from blocking reordering of pages (Andy Babic, Sage Abdullah)
* Fix: Improve layout of object permissions table (Sage Abdullah)
* Fix: Fix typo in aria-label attribute of page explorer navigation link (Sébastien Corbin)
* Fix: Reinstate transparency indicator on image chooser widgets (Sébastien Corbin)
* Fix: Remove table headers that have no text (Matt Westcott)
* Fix: Fix broken link to user search (Shlomo Markowitz)
* Fix: Ensure that JS slugify function strips Unicode characters disallowed by Django slug validation (Atif Khan)
* Fix: Do not show notices about root / unroutable pages when searching or filtering in the page explorer (Matt Westcott)
* Fix: Resolve contrast issue for page deletion warning (Sanjeev Holla S)
* Fix: Make sure content metrics falls back to body element only when intended (Sage Abdullah)
* Fix: Remove wrongly-added filters from redirects index (Matt Westcott)
* Fix: Prevent popular tags filter from generating overly complex queries when not filtering (Matt Westcott)
* Fix: Fix content path links in usage view to scroll to the correct element (Sage Abdullah)
* Fix: Always show the minimap toggle button (Albina Starykova)
* Fix: Ensure that dropdown button toggles show with a border in high contrast mode (Ishwari8104, LB (Ben) Johnston)
* Fix: Update email notification header to the new logo design (Rahul Samant)
* Fix: Change `file_size` field on document model to avoid artificial 2Gb limit (Gabriel Getzie)
* Fix: Ensure that `TypedTableBlock` uses the correct API representations of child blocks (Matt Westcott)
* Fix: Footer action buttons now include their `media` definitions (Sage Abdullah)
* Fix: Improve the text contrast of the bulk actions "Select all" button (Sage Abdullah)
* Fix: Fix error on workflow settings view with multiple snippet types assigned to the same workflow on Postgres (Sage Abdullah)
* Fix: Fix datetime fields overflowing its parent wrapper in listing filters (Rohit Singh)
* Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
* Fix: Improve layout of report listing tables (Sage Abdullah)
* Fix: Fix regression from creation of `AbstractGroupApprovalTask` to ensure `can_handle` checks for the abstract class correctly (Sumana Sree Angajala)
* Docs: Upgrade Sphinx to 7.3 (Matt Westcott)
* Docs: Upgrade sphinx-wagtail-theme to v6.4.0, with a new search integration and Read the Docs Addons bug fixes (Thibaud Colas)
* Docs: Document how to customize date/time format settings (Vince Salvino)
* Docs: Create a new documentation section for deployment and move fly.io deployment from the tutorial to this section (Vince Salvino)
* Docs: Clarify process for UserViewSet customization (Sage Abdullah)
* Docs: Correct `WAGTAIL_WORKFLOW_REQUIRE_REAPPROVAL_ON_EDIT` documentation to state that it defaults to `False` (Matt Westcott)
* Docs: Add an example of customizing a default accessibility check (Cynthia Kiser)
* Docs: Demonstrate access protection with `TokenAuthentication` in the Wagtail API v2 Configuration Guide (Krzysztof Jeziorny)
* Docs: Replace X links with Mastodon in the README (Alex Morega)
* Docs: Re-enable building offline formats in online documentation (Read the docs) for EPUB/PDF/HTML downloads (Joel William, Sage Abdullah)
* Docs: Resolve multiple output errors in the documentation ePub format (Sage Abdullah)
* Docs: Update social media examples to use LinkedIn, Reddit, Facebook (Ayaan Qadri)
* Maintenance: Removed support for Python 3.8 (Matt Westcott)
* Maintenance: Drop pytz dependency in favour of `zoneinfo.available_timezones` (Sage Abdullah)
* Maintenance: Relax django-taggit dependency to allow 6.0 (Matt Westcott)
* Maintenance: Improve page listing performance (Sage Abdullah)
* Maintenance: Phase out usage of SECRET_KEY in version and icon hashes (Jake Howard)
* Maintenance: Audit all use of localized and non-localized numbers in templates (Matt Westcott)
* Maintenance: Refactor StreamField `get_prep_value` for closer alignment with JSONField (Sage Abdullah)
* Maintenance: Move search implementation logic from generic `IndexView` to `BaseListingView` (Sage Abdullah)
* Maintenance: Upgrade Puppeteer integration tests for reliability (Matt Westcott)
* Maintenance: Restore ability to use `.in_bulk()` on specific querysets under Django 5.2a0 (Sage Abdullah)
* Maintenance: Add generated `test-media` to .gitignore (Shlomo Markowitz)
* Maintenance: Improve `debounce` util's return type for better TypeScript usage (Sage Abdullah)
* Maintenance: Ensure the side panel's show event is dispatched after any hide events (Sage Abdullah)
* Maintenance: Migrate preview-panel JavaScript to Stimulus & TypeScript, add full unit testing (Sage Abdullah)
* Maintenance: Move `wagtailConfig` values from inline scripts to the `wagtail_config` template tag (LB (Ben) Johnston, Sage Abdullah)
* Maintenance: Deprecate the `{% locales %}` and `{% js_translation_strings %}` template tags (LB (Ben) Johnston, Sage Abdullah)
* Maintenance: Ensure multi-line comments are cleaned from custom icons in addition to just single line comments (Jake Howard)
* Maintenance: Deprecate `window.wagtailConfig.BULK_ACTION_ITEM_TYPE` usage in JavaScript to reduce reliance on inline scripts (LB (Ben) Johnston)
* Maintenance: Remove `window.fileupload_opts` usage in JavaScript, use data attributes on fields instead to reduce reliance on inline scripts (LB (Ben) Johnston)
* Maintenance: Remove `image_format_name_to_content_type` helper function that duplicates Willow functionality (Matt Westcott)
* Maintenance: Improve code reuse for footer actions markup across generic views (Sage Abdullah)
* Maintenance: Deprecate internal `DeleteMenuItem` API for footer actions (Sage Abdullah)
* Maintenance: Update Pillow dependency to allow 11.x (Storm Heg)
6.2.3 (01.11.2024)
~~~~~~~~~~~~~~~~~~
@ -421,7 +58,6 @@ Changelog
* Add "soft" client-side validation for `StreamBlock` / `ListBlock` `min_num` / `max_num` (Matt Westcott)
* Log accessibility checker results in the console to help developers with troubleshooting (Thibaud Colas)
* Disable pointer events on checker highlights to simplify DevTools inspections (Thibaud Colas)
* `StaticBlock` now renders nothing by default when no template is specified (Sævar Öfjörð Magnússon)
* Fix: Make `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` setting functional again (Rohit Sharma)
* Fix: Enable `richtext` template tag to convert lazy translation values (Benjamin Bach)
* Fix: Ensure permission labels on group permissions page are translated where available (Matt Westcott)
@ -446,8 +82,6 @@ Changelog
* Fix: Fix focal point chooser when localization enabled (Sébastien Corbin)
* Fix: Ensure that system checks for `WAGTAIL_DATE_FORMAT`, `WAGTAIL_DATETIME_FORMAT` and `WAGTAIL_TIME_FORMAT` take `FORMAT_MODULE_PATH` into account (Sébastien Corbin)
* Fix: Prevent rich text fields inside choosers from being duplicated when opened repeatedly (Sage Abdullah)
* Fix: Prevent history view from breaking if a log entry's revision is missing (Matt Westcott)
* Fix: Prevent long filenames from breaking layout on document chooser listings (Frank Yiu, Shaurya Panchal)
* Docs: Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
* Docs: Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
* Docs: Document Wagtail's bug bounty policy (Jake Howard)
@ -465,7 +99,7 @@ Changelog
* Maintenance: Split `contrib.frontend_cache.backends` into dedicated sub-modules (Andy Babic)
* Maintenance: Remove unused `docs/autobuild.sh` script (Sævar Öfjörð Magnússon)
* Maintenance: Replace `urlparse` with `urlsplit` to improve performance (Jake Howard)
* Maintenance: Optimize embed finder lookups (Jake Howard)
* Maintenance: Optimise embed finder lookups (Jake Howard)
* Maintenance: Improve performance of initial admin loading by moving sprite hashing out of module import time (Jake Howard)
* Maintenance: Remove workaround and inline scripts for activating workflow actions (Sage Abdullah)
* Maintenance: Prevent `'BlockWidget' object has no attribute '_block_json'` from masking errors during StreamField serialization (Matt Westcott)
@ -530,7 +164,7 @@ Changelog
* Update the minimum version of `djangorestframework` to 3.15.1 (Sage Abdullah)
* Add support for related fields in generic `IndexView.list_display` (Abdelrahman Hamada)
* Improve page fetching logic and cache route results per request (Gordon Pendleton)
* Optimize rewriting of links / embeds in rich text using bulk database lookups (Andy Chosak)
* Optimise rewriting of links / embeds in rich text using bulk database lookups (Andy Chosak)
* Add normalization mechanism to StreamField so that assignments and defaults can be passed in a wider range of data types (Joshua Munn, Matt Westcott)
* Allow specifying a `STORAGES` alias name for `WAGTAILIMAGES_RENDITION_STORAGE` (Alec Baron)
* Update `PASSWORD_REQUIRED_TEMPLATE` setting to `WAGTAIL_PASSWORD_REQUIRED_TEMPLATE` with deprecation of previous naming (Saksham Misra, LB (Ben) Johnston)
@ -562,9 +196,6 @@ Changelog
* Fix: Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
* Fix: Reinstate missing static files in style guide (Sage Abdullah)
* Fix: Provide `convert_mariadb_uuids` management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
* Fix: Ensure invalid submissions are marked as dirty edits on load to trigger UI and browser warnings for unsaved changes, restoring previous behavior from Wagtail 5.2 (Sage Abdullah)
* Fix: Update polldaddy oEmbed provider to use the crowdsignal URL (Matthew Scouten)
* Fix: Remove polleverywhere oEmbed provider as it this application longer supports oEmbed (Matthew Scouten)
* Docs: Add contributing development documentation on how to work with a fork of Wagtail (Nix Asteri, Dan Braghis)
* Docs: Make sure the settings panel is listed in tabbed interface examples (Tibor Leupold)
* Docs: Update content and page names to their US spelling instead of UK spelling (Victoria Poromon)
@ -605,7 +236,6 @@ Changelog
* Maintenance: Remove jQuery usage in telepath widget classes (Matt Westcott)
* Maintenance: Remove `xregexp` (IE11 polyfill) along with `window.XRegExp` global util (LB (Ben) Johnston)
* Maintenance: Refactor the Django port of `urlify` to use TypeScript, officially deprecate `window.URLify` global util (LB (Ben) Johnston)
* Maintenance: Adopt the modern best practice for `beforeunload` usage in `UnsavedController` to trigger a leave page warning when edits have been made (Shubham Mukati, Sage Abdullah)
6.0.6 (11.07.2024)
@ -828,16 +458,6 @@ Changelog
* Maintenance: Remove support for Django 4.1 and below (Sage Abdullah)
5.2.8 (03.02.2025)
~~~~~~~~~~~~~~~~~~
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
* Fix: Handle StreamField migrations where the field value is null (Joshua Munn)
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
5.2.7 (01.11.2024)
~~~~~~~~~~~~~~~~~~
@ -960,7 +580,7 @@ Changelog
* Support extending Wagtail client-side with Stimulus (LB (Ben) Johnston)
* Update all `FieldPanel('title')` examples to use the recommended `TitleFieldPanel('title')` panel (Chinedu Ihedioha)
* The `purge_revisions` management command now respects revisions that have a `on_delete=PROTECT` foreign key relation and won't delete them (Neeraj P Yetheendran, Meghana Reddy, Sage Abdullah, Storm Heg)
* Add support for Shift + Click behavior in form submissions and simple translations submissions (LB (Ben) Johnston)
* Add support for Shift + Click behaviour in form submissions and simple translations submissions (LB (Ben) Johnston)
* Improve filtering of audit logging based on the user's permissions (Stefan Hammer)
* Fix: Ensure that StreamField's `FieldBlock`s correctly set the `required` and `aria-describedby` attributes (Storm Heg)
* Fix: Avoid an error when the moderation panel (admin dashboard) contains both snippets and private pages (Matt Westcott)
@ -1022,7 +642,7 @@ Changelog
* Maintenance: Deprecate legacy URL redirects in `ModelViewSet` and `SnippetViewSet` (Sage Abdullah)
* Maintenance: Simplify code for registering page listing action buttons (Matt Westcott)
* Maintenance: Removed the unused, legacy, Wagtail userbar views set up for an old iframe approach (Sage Abdullah)
* Maintenance: Optimize `lru_cache` usage (Jake Howard)
* Maintenance: Optimise `lru_cache` usage (Jake Howard)
* Maintenance: Implement `date_since` in `get_most_popular` inside `search_promotions.models.Query` (TopDevPros)
* Maintenance: Refactor generic view subclasses to better reuse the generic templates and breadcrumbs (Sage Abdullah)
* Maintenance: Adopt consistent `classname` (not `classnames`) attributes for all `MenuItem` usage, including deprecation warnings (LB (Ben) Johnston)
@ -1162,7 +782,7 @@ Changelog
* Maintenance: Optimise use of `specific` on Task and TaskState (Matt Westcott)
* Maintenance: Use table UI component for workflow task index view (Matt Westcott)
* Maintenance: Make header search available on generic index view (Matt Westcott)
* Maintenance: Update pagination behavior to reject out-of-range / invalid page numbers (Matt Westcott)
* Maintenance: Update pagination behaviour to reject out-of-range / invalid page numbers (Matt Westcott)
* Maintenance: Remove color tokens which are duplicates / unused (Thibaud Colas)
* Maintenance: Add tests to help with maintenance of theme color tokens (Thibaud Colas)
* Maintenance: Split out a base listing view from generic index view (Matt Westcott)
@ -4401,7 +4021,7 @@ Changelog
* Fix: Fixed TypeError when getting embed HTML with oembed on Python 3 (John-Scott Atlakson)
* Fix: Made HTML whitelisting in rich text fields more robust at catching disallowed URL schemes such as "jav\tascript:" (Tim Heap)
* Fix: created_at timestamps on page revisions were not being preserved on page copy, causing revisions to get out of sequence
* Fix: When copying pages recursively, revisions of subpages were being copied regardless of the copy_revisions flag
* Fix: When copying pages recursively, revisions of sub-pages were being copied regardless of the copy_revisions flag
* Fix: Updated the migration dependencies within the project template to ensure that Wagtail's own migrations consistently apply first.
* Fix: The cache of site root paths is now cleared when a site is deleted.
* Fix: Search indexing now prevents pages from being indexed multiple times, as both the base Page model and the specific subclass

Wyświetl plik

@ -5,7 +5,7 @@
* Cynthia Kiser (Caltech)
* Dan Braghis (Torchbox)
* Dawn Wages (The Wharton School)
* Emily Topp-Mugglestone (Torchbox)
* Jacob Topp-Mugglestone (Torchbox)
* Jake Howard (Torchbox)
* Kalob Taulien
* LB Johnston
@ -15,7 +15,6 @@
* Sævar Öfjörð Magnússon (Overcast)
* Sage Abdullah (Torchbox)
* Scott Cranfill (JPL)
* Sébastien Corbin
* Stefan Hammer (wunderweiss)
* Storm Heg
* Thibaud Colas (Torchbox)
@ -720,6 +719,7 @@
* Kevin Chung (kev-odin)
* valnuro
* Vitaly Babiy
* Sébastien Corbin
* Sahil Jangra
* Henry Harutyunyan
* Alex Morega
@ -743,6 +743,7 @@
* Sandro Rodrigues
* Brian Mugo
* Panagiotis H.M. Issaris
* Damilola Oladele
* Olumide Micheal
* Chiemezuo Akujobi
* Krish Soni
@ -826,63 +827,11 @@
* Romein van Buren
* Chris Shenton
* Nathanaël Jourdane
* Vaughn Dickson
* Ansuman Shukla
* Nayanshi Singh
* Daniel Black
* Atif Khan
* Sanjeev Holla S
* Shubham Mukati
* Matthew Scouten
* Ishwari8104
* Rahul Samant
* Gabriel Getzie
* Rohit Singh
* Robin Varghese
* Victoria Ottah
* Bart Cieliński
* alexkiro
* Ankit Kumar
* Frank Yiu
* Shaurya Panchal
* Sumana Sree Angajala
* Srishti Jaiswal
* Alessandro Chitarrini
* Joel William
* Ataf Fazledin Ahamed
* Ayaan Qadri
* manu
* Aayushman Singh
* Steven Steinwand
* Clifford Gama
* Noah van der Meer
* Strapchay
* Alex Fulcher
* Harsh Dange
* Mauro Soche
* Krystian Magdziarz
* Guilhem Saurel
* James Harrington
* Unyime Emmanuel Udoh
* Joren Hammudoglu
* Rishabh Sharma
* Mike Gifford
* Stéphane Blondon
* Jatin Bhardwaj
* Mohamed Rabiaa
* Bernhard Bliem
* Mahmoud Nasser
* Prabhpreet Kaur
* Baptiste Mispelon
* Mohammad Fathi Rahman
* Ashish Nagmoti
* Dhruvi Patel
* Sylvain Boissel
## Translators
* Afrikaans: Jaco du Plessis, Jared Osborn
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Tarek Berkane, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
* Armenian: Vachagan
* Azerbaijani: Mirza Iskandarov
* Bangla: Mahmud Abdur Rahman
@ -898,11 +847,11 @@
* Czech: Ales Dvorak, Jan Feřtek, Martin Galda, IT Management, Tomáš Jeřábek, Vláďa Macek, Eva Mikesova, Mořeplavec, Sophy O, Martina Oleksakova, Kryštof Pilnáček, Tomáš Podivínský, Ivan Pomykacz, Jiri Stepanek, Marek Turnovec, Mirek Zvolský
* Danish: Benjamin Bach, Mads Kronborg, MRostgaard, Asger Sørensen
* Divehi: Fauzaan Gasim
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Joeri Vlekken, Richard Voorhorst
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Richard Voorhorst
* English (India): Neeraj PY, Apoorv Saini
* Estonian: Erlend Eelmets, Martin, Ragnar Rebase
* Finnish: Jiri Grönroos, Eetu Häivälä, Niklas Jerva, Aarni Koskela, Rauli Laine, Valter Maasalo, Glen Somerville, Juha Yrjölä
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Christophe Chauvet, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
* Galician: X Bello, Amós Oviedo
* Georgian: André Bouatchidzé
* German: Ettore Atalan, Bohreromir, Matti Borchers, Benedikt Breinbauer, Donald Buczek, Patrick Craston, Peter Dreuw, Oliver Engel, Stefan Hammer, Patrick Hebner, Krzysztof Jeziorny, Benjamin Kaspar, Henrik Kröger, Tibor L, Tammo van Lessen, Martin Löhle, Wasilis Mandratzis-Walz, Daniel Manser, Matthias Martin, m0rph3u5, Max Pfeiffer, Moritz Pfeiffer, Herbert Poul, Karl Sander, Tobias Schmidt, Scriptim, Johannes Spielmann, Raphael Stolt, Benjamin Thurm, Norman Uekermann, unicode_it, Jannis Vajen, Florian Vogt, Alexander Weiß, Matthew Westcott, Benedikt Willi
@ -940,4 +889,4 @@
* Ukrainian: Yuri Fabirovsky, Vladislav Herasimenko, Mikolai Incognito, Anastasiia La, Sergiy Shkodenko, Viktor Shytiuk, Ivan Tyshchenko, Zoriana Zaiats, Mykola Zamkovoi
* Uyghur: Abduqadir Abliz, Azat
* Vietnamese: Amelia Dao, Duc Huynh, Hồng Quân Nguyễn, Luan Nguyen, Vu Pham, stdpi
* Welsh: Philip Lindsay-Crisp, Adam Hughes
* Welsh: Philip Crisp, Adam Hughes

Wyświetl plik

@ -14,7 +14,7 @@ clean-pyc:
find . -name '*~' -exec rm -f {} +
develop: clean-pyc
pip install -e .[testing,docs] --config-settings editable-mode=strict
pip install -e .[testing,docs]
npm install --no-save && npm run build
lint-server:

Wyświetl plik

@ -19,8 +19,8 @@
<a href="https://pypi.python.org/pypi/wagtail/">
<img src="https://img.shields.io/pypi/dm/wagtail?logo=Downloads" alt="Monthly downloads" />
</a>
<a href="https://fosstodon.org/@wagtail">
<img src="https://img.shields.io/mastodon/follow/109308882653647818?domain=https%3A%2F%2Ffosstodon.org&style=social" alt="Follow @wagtail@fosstodon.org">
<a href="https://twitter.com/WagtailCMS">
<img src="https://img.shields.io/twitter/follow/WagtailCMS?style=social&logo=twitter" alt="follow on Twitter">
</a>
</p>
@ -28,6 +28,13 @@ Wagtail is an open source content management system built on Django, with a stro
![Wagtail screenshot](https://cdn.jsdelivr.net/gh/wagtail/wagtail@main/.github/wagtail-screenshot-with-browser.png)
### Join the Community at Wagtail Space! 🚀
Wagtail Space is coming in June 2024! Don't miss your chance to meet other Wagtailers in person. The Call for Participation and registration for both Wagtail Space 2024 events is open. We'd love to have you give a talk, contribute to a sprint, or join us as an attendee in June.
* [Wagtail Space NL](https://nl.wagtail.space/), Arnhem, The Netherlands. 2024-06-12 - 2024-06-14
* [Wagtail Space US](https://us.wagtail.space/), Philadelphia, PA. 2024-06-20 to 2024-06-22
### 🔥 Features
- A fast, attractive interface for authors
@ -70,7 +77,7 @@ Wagtail is used by [NASA](https://www.nasa.gov/), [Google](https://www.google.co
### 📖 Documentation
[docs.wagtail.org](https://docs.wagtail.org/) is the full reference for Wagtail, and includes guides for developers, designers and editors, alongside [release notes](https://docs.wagtail.org/en/stable/releases/) and our [roadmap](https://wagtail.org/roadmap/).
[docs.wagtail.org](https://docs.wagtail.org/) is the full reference for Wagtail, and includes guides for developers, designers and editors, alongside release notes and our roadmap.
For those who are **new to Wagtail**, the [Zen of Wagtail](https://docs.wagtail.org/en/stable/getting_started/the_zen_of_wagtail.html) will help you understand what Wagtail is, and what Wagtail is _not_.
@ -84,11 +91,11 @@ _(If you are reading this on GitHub, the details here may not be indicative of t
Wagtail supports:
- Django 4.2.x and 5.1.x
- Python 3.9, 3.10, 3.11, 3.12 and 3.13
- PostgreSQL, MySQL, MariaDB and SQLite (with JSON1) as database backends
- Django 4.2.x and 5.0.x
- Python 3.8, 3.9, 3.10, 3.11 and 3.12
- PostgreSQL, MySQL and SQLite (with JSON1) as database backends
[Previous versions of Wagtail](https://docs.wagtail.org/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7, 3.8 and earlier Django versions.
[Previous versions of Wagtail](https://docs.wagtail.org/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7, 3.7 and earlier Django versions.
---

Wyświetl plik

@ -13,7 +13,7 @@ The following organisations and individuals supported the [Wagtail's First Hatch
- [Taywa](https://www.taywa.ch/)
- [Rock Kitchen Harris](https://www.rkh.co.uk/)
- [The Motley Fool](https://www.fool.com/)
- [R Strother Scott](https://x.com/rstrotherscott)
- [R Strother Scott](https://twitter.com/rstrotherscott)
- [Beyond Media](https://www.beyond.works/)
The features below were developed thanks to the sponsorship of these organsations:
@ -38,7 +38,7 @@ The features below were developed thanks to the sponsorship of these organsation
- Page aliases - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
- Hooks for Snippet customization - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
- Hooks for Snippet customisation - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
- Utility for testing hooks - [The Mozilla Foundation](https://foundation.mozilla.org/en/)

Wyświetl plik

@ -1 +1 @@
@forward 'settings/variables';
@import 'settings/variables';

Wyświetl plik

@ -3,8 +3,8 @@ These are functions and mixins.
No CSS should be produced by these files.
*/
@forward 'tools/functions.breakpoints';
@forward 'tools/mixins.breakpoints';
@forward 'tools/mixins.general';
@forward 'tools/mixins.grid';
@forward 'tools/mixins.guide-line';
@import 'tools/functions.breakpoints';
@import 'tools/mixins.breakpoints';
@import 'tools/mixins.general';
@import 'tools/mixins.grid';
@import 'tools/mixins.guide-line';

Wyświetl plik

@ -1,22 +1,13 @@
@use '../tools' as *;
.w-a11y-result__row {
@include box;
padding: theme('spacing.4');
display: flex;
justify-content: space-between;
background-color: theme('colors.surface-page');
padding: theme('spacing.4');
border-radius: theme('borderRadius.DEFAULT');
color: theme('colors.text-context');
border: 1px solid theme('colors.border-furniture');
// Shows additional details within the CMS only.
.form-side--checks & {
display: block;
}
@include more-contrast() {
border-color: theme('colors.border-furniture-more-contrast');
}
}
.w-a11y-result__header {

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
// user avatars
.avatar {
border-radius: 100%;
@ -31,12 +29,9 @@
}
&.large {
width: 60px;
height: 60px;
@include media-breakpoint-up(sm) {
width: 80px;
height: 80px;
width: 70px;
height: 70px;
}
}
@ -44,33 +39,3 @@
border-radius: 0;
}
}
.avatar--edit {
overflow: visible;
flex-shrink: 0;
img {
border-radius: 50%;
z-index: auto;
}
}
.avatar__edit-link {
width: theme('spacing.5');
height: theme('spacing.5');
border-radius: 50%;
border: theme('spacing.px') solid theme('colors.border-furniture');
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 100%;
inset-inline-start: 50%;
transform: translate(calc(var(--w-direction-factor) * -50%), -50%);
background-color: theme('colors.surface-page');
.icon {
width: theme('spacing.[2.5]');
height: theme('spacing.[2.5]');
}
}

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.w-breadcrumbs:not(.editor-view .w-breadcrumbs) {
@apply sm:w-py-2.5;

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.bulk-actions-filter-checkbox {
.table-headers & {
> div {
@ -65,10 +63,7 @@
}
.num-objects-in-listing {
// This is inside the footer, which has a dark indigo background in light
// mode, so we want to use the absolute value of dark mode's
// text-link-default instead of its dynamic value.
color: theme('colors.secondary.100');
color: theme('colors.text-link-default');
background-color: transparent;
border: 0;
font-family: theme('fontFamily.sans');

Wyświetl plik

@ -3,8 +3,6 @@
// Core button styles
@use 'sass:color';
@use '../tools' as *;
@use '../settings' as *;
.button {
border-radius: theme('borderRadius.sm');
@ -327,8 +325,7 @@
align-items: center;
justify-content: center;
gap: theme('spacing.1');
height: theme('spacing.8');
min-width: theme('spacing.8');
height: theme('spacing.7');
appearance: none;
background-color: initial;
border: 1px solid transparent;
@ -338,8 +335,6 @@
font-weight: theme('fontWeight.medium');
cursor: pointer;
@include more-contrast-interactive();
.icon {
width: theme('spacing.4');
height: theme('spacing.4');

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:math';
@use '../tools' as *;
$preview-size: 2.625rem; // 42px
@ -23,8 +22,6 @@ $preview-size: 2.625rem; // 42px
border-color: transparent;
padding: theme('spacing.[1.5]');
@include more-contrast-interactive();
.icon {
@include svg-icon(theme('spacing.4'), initial);
color: inherit;
@ -84,6 +81,11 @@ $preview-size: 2.625rem; // 42px
width: auto;
}
.chooser .w-dropdown__toggle--icon {
width: $preview-size;
height: $preview-size;
}
// Display these as inline block so that action icons such as comments can appear as close as possible
.w-field--admin_task_chooser,
.w-field--admin_page_chooser,

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.w-dialog {
--w-dialog-close-icon-color: theme('colors.icon-primary');

Wyświetl plik

@ -1,7 +1,4 @@
// stylelint-disable selector-attribute-name-disallowed-list
@use '../tools' as *;
@use '../settings' as *;
$separator: 1px solid theme('colors.white-15');
$radius: theme('borderRadius.sm');
@ -29,7 +26,17 @@ $radius: theme('borderRadius.sm');
width: 100%;
}
&:has(:not([hidden]) > [data-placement^='bottom']) {
@supports not selector(:has(*)) {
// Use no corner radius and always-on borders if `:has` is not supported.
--primary-button-radius-top: 0;
--primary-button-radius-bottom: 0;
--toggle-button-radius-top: 0;
--toggle-button-radius-bottom: 0;
--first-item-border-top: #{$separator};
--last-item-border-top: #{$separator};
}
&:has([data-placement^='bottom']) {
--primary-button-radius-top: #{$radius};
--primary-button-radius-bottom: 0;
--toggle-button-radius-top: #{$radius};
@ -39,7 +46,7 @@ $radius: theme('borderRadius.sm');
--first-item-border-top: #{$separator};
}
&:has(:not([hidden]) > [data-placement^='top']) {
&:has([data-placement^='top']) {
--primary-button-radius-top: 0;
--primary-button-radius-bottom: #{$radius};
--toggle-button-radius-top: 0;
@ -118,3 +125,8 @@ $radius: theme('borderRadius.sm');
border-bottom-color: theme('colors.warning.100');
}
}
// Reduces the visibility of secondary actions like "Unpublish" or "Delete".
.w-dropdown-button .action-secondary {
color: theme('colors.text-label-menus-default');
}

Wyświetl plik

@ -1,9 +1,9 @@
.w-dropdown__toggle {
@apply w-px-2 w-text-text-label w-bg-transparent w-border-2 w-border-transparent;
@apply w-px-2 w-text-text-label w-bg-transparent;
}
.w-dropdown__toggle--icon {
@apply w-w-8 w-h-8 more-contrast:w-p-0 more-contrast:w-border more-contrast:w-rounded-sm more-contrast:w-border-border-interactive-more-contrast hover:more-contrast:w-border-border-interactive-more-contrast-hover;
@apply w-w-8 w-h-8;
}
.w-dropdown__toggle-icon {

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.filterable {
display: grid;
grid-template-columns: 1fr minmax(theme('spacing.48'), theme('spacing.64'));
@ -36,8 +34,6 @@
color: theme('colors.text-link-default');
background-color: theme('backgroundColor.surface-header');
@include more-contrast-interactive();
.icon {
width: theme('fontSize.16');
height: theme('fontSize.16');

Wyświetl plik

@ -1,6 +1,4 @@
@use 'sass:math';
@use '../tools' as *;
@use '../settings' as *;
.footer {
@include transition(bottom 0.5s ease 1s);
@ -32,9 +30,8 @@
.footer__container {
border-radius: theme('borderRadius.sm') theme('borderRadius.sm') 0 0;
background: theme('colors.surface-menus');
color: theme('colors.text-button');
color: theme('colors.text-label-menus-default');
transition: transform 1s;
padding: theme('spacing.1');
@include media-breakpoint-down(xs) {
width: 100%;
@ -63,18 +60,22 @@
}
.footer__save-warning {
font-size: theme('fontSize.14');
height: 100%;
font-size: 0.95em;
display: flex;
flex-direction: row;
justify-content: center;
.icon {
font-size: 1.2em;
margin-inline-end: 0.5em;
}
p {
margin: 0;
margin: -0.2em 0 0 0;
}
@include media-breakpoint-up(sm) {
margin-inline-end: theme('spacing[1.5]');
margin-inline-end: 50px;
align-items: center;
}
}
@ -133,13 +134,7 @@
.actions .w-dropdown-button {
width: 100%;
.w-dropdown .button {
font-size: theme('fontSize.14');
font-weight: 500;
}
> .button {
font-size: theme('fontSize.16');
flex-grow: 1;
}
}

Wyświetl plik

@ -1,7 +1,6 @@
@use 'sass:color';
@use 'sass:map';
@use 'sass:math';
@use '../tools' as *;
.side-panel-open {
@apply w-overflow-y-hidden sm:w-overflow-y-auto;
@ -37,8 +36,7 @@
sm:w-max-w-[22.5rem]
md:w-max-w-[35.937rem]
lg:w-max-w-[31.25rem]
xl:w-max-w-[46.875rem]
more-contrast:w-border-border-furniture-more-contrast;
xl:w-max-w-[46.875rem];
z-index: calc(theme('zIndex.header') - 10);
width: var(--side-panel-width, 100%);
@ -86,6 +84,13 @@
&:focus-within:has(:focus-visible) {
@include focus-outline;
}
@supports not selector(:focus-visible) {
&:focus-within {
/* Fallback for browsers without :focus-visible support */
@include focus-outline;
}
}
}
&__resize-grip-icon {

Wyświetl plik

@ -1,6 +1,3 @@
@use '../tools' as *;
@use '../settings' as *;
.wrapper {
@include clearfix();
@apply w-transition-sidebar;
@ -17,30 +14,27 @@
}
/**
* Increase the scroll offset to account for pages with sticky areas - header or footer.
* Increase the scroll offset to account for pages with a sticky header.
* We apply this to all pages for simplicity.
*/
@mixin sticky-areas-scroll-offset() {
@mixin slim-header-scroll-offset() {
$gap: theme('spacing.4');
// For mobile viewports, expect a sticky header over two rows.
scroll-padding-top: calc(theme('spacing.slim-header') * 2 + $gap);
@include media-breakpoint-up(sm) {
scroll-padding-top: calc(theme('spacing.slim-header') + $gap);
// Increase the scroll offset to account for pages with sticky bottom button
scroll-padding-bottom: 100px;
}
}
.content-wrapper {
@include slim-header-scroll-offset();
scroll-behavior: smooth;
width: 100%;
height: 100%; // this has no effect on desktop, but on mobile it helps aesthetics of menu popout action
float: inline-start;
position: relative;
border-bottom: 1px solid theme('colors.border-furniture');
@include sticky-areas-scroll-offset();
}
.content {

Wyświetl plik

@ -1,7 +1,5 @@
@use 'sass:math';
@use 'sass:color';
@use '../tools' as *;
@use '../settings' as *;
.w-header {
@apply w-text-text-label;
@ -29,6 +27,10 @@
max-width: 1em;
max-height: 1em;
}
&.avatar {
margin-inline-start: calc(0 - theme('spacing.2'));
}
}
.w-header__subtitle {
@ -36,6 +38,11 @@
font-weight: theme('fontWeight.normal');
}
.w-header__description {
font-size: theme('fontSize.18');
font-weight: theme('fontWeight.normal');
}
// Give padding to the rows inside of headers so that nested breadcrumbs aren't padded by their parent header el.
// Use w-header--with-padding for headers that don't contain .row elements.
&.w-header--with-padding,
@ -97,6 +104,10 @@
margin-inline-end: 2em;
}
.avatar.small {
margin-inline-start: 0;
}
a {
font-weight: theme('fontWeight.bold');
}
@ -115,6 +126,12 @@
padding-inline-start: 0;
}
.w-header__glyph {
&.avatar {
margin-inline-start: calc(0 - theme('spacing.9'));
}
}
.left {
float: inline-start;
margin-inline-end: 0;
@ -153,10 +170,6 @@
}
.w-slim-header {
@include more-contrast() {
border-color: theme('colors.border-furniture-more-contrast');
}
&__search-form {
@apply w-mx-2 w-flex w-items-center w-gap-2;
}

Wyświetl plik

@ -1,6 +1,5 @@
@use 'sass:color';
@use 'sass:map';
@use '../tools' as *;
// Help text formatters
.help-block {
padding: 1em;

Wyświetl plik

@ -1,6 +1,4 @@
@use 'sass:string';
@use '../tools' as *;
@use '../settings' as *;
// Set SVG icons to use the current text color in the location they appear as
// their default fill color. Can be overridden for a specific icon by either

Wyświetl plik

@ -1,17 +1,3 @@
.indicator {
margin-inline-end: 0;
opacity: theme('opacity.70');
.icon {
padding: 2px;
vertical-align: middle; // reset vertical-align set by icon.initial
}
&--is-dimmed {
opacity: theme('opacity.50');
}
}
.privacy-indicator {
&.public {
.label-private {
@ -25,3 +11,31 @@
}
}
}
.indicator {
font-size: 1em;
margin-inline-end: 0;
opacity: theme('opacity.70');
.icon {
border: 1px solid transparent;
border-radius: 50%;
font-size: 1.25em;
padding: 2px;
vertical-align: middle; // reset vertical-align set by icon.initial
@media (forced-colors: active) {
background-color: ButtonText;
}
}
&.indicator--is-inverse {
.icon {
border-color: theme(
'colors.surface-page'
); // ensure border is available for high contrast mode
background-color: theme('colors.text-context');
color: theme('colors.surface-page');
}
}
}

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
/* stylelint-disable selector-max-combinators */
// General listings, like for pages, images or snippets
ul.listing {
@ -29,7 +27,6 @@ ul.listing {
td,
th {
text-align: start;
padding: calc(1em * var(--w-density-factor)) 0.3em;
@include media-breakpoint-up(sm) {
@ -52,7 +49,6 @@ ul.listing {
td {
vertical-align: middle;
overflow-wrap: anywhere;
}
td.title {
@ -66,6 +62,7 @@ ul.listing {
th {
font-size: 0.9em;
text-align: start;
font-weight: normal;
white-space: nowrap;
}
@ -90,8 +87,8 @@ ul.listing {
}
&:has(
td:first-child input[type='checkbox']:only-child,
th:first-child input[type='checkbox']:only-child
td:first-child input[type='checkbox'],
th:first-child input[type='checkbox']
) {
td:first-child,
th:first-child {
@ -100,7 +97,6 @@ ul.listing {
width: theme('spacing.10');
text-align: center;
// stylelint-disable-next-line selector-max-specificity
input[type='checkbox'] {
margin-inline-end: 0;
}
@ -368,79 +364,6 @@ ul.listing {
@include transition(border-color 0.2s ease);
border: 3px solid theme('colors.surface-page');
}
&--dashboard {
margin-bottom: 0;
tbody {
border-bottom: 0;
}
td:first-child {
padding-inline-start: theme('spacing.6');
}
td:last-child {
padding-inline-end: theme('spacing.6');
}
.title a {
font-weight: theme('fontWeight.medium');
}
.w-status--label {
float: inline-end;
font-size: inherit;
}
.indicator .icon {
padding: 0;
}
.privacy-indicator {
margin-inline-end: theme('spacing.2');
// Adjust icon size to closely match the appearance of the adjacent 'locked' icon
.icon-no-view {
width: 1.1em;
height: 1.1em;
}
}
.tasks {
text-wrap: nowrap;
}
.actions li {
float: inline-end;
}
@include media-breakpoint-down(md) {
display: grid;
tr {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: theme('spacing.2');
padding: theme('spacing.5');
}
td,
td:first-child,
td:last-child {
padding: 0;
}
.title {
width: 100%;
}
.actions-container {
margin-inline-start: auto;
}
}
}
}
.image-choice {
@ -651,8 +574,8 @@ table.listing {
}
&:has(
td:first-child input[type='checkbox']:only-child,
th:first-child input[type='checkbox']:only-child
td:first-child input[type='checkbox'],
th:first-child input[type='checkbox']
) {
// Bulk actions, match the width of the header spacing up until
// the page title (final breadcrumb item):
@ -673,8 +596,8 @@ table.listing {
// custom ordering is active, as the padding to match the breadcrumbs is
// already handled by the first column.
&:has(
td:first-child input[type='checkbox']:only-child,
th:first-child input[type='checkbox']:only-child,
td:first-child input[type='checkbox'],
th:first-child input[type='checkbox'],
.ord
) {
th:nth-child(2),
@ -687,19 +610,17 @@ table.listing {
// - no nice padding is applied,
// - we're not in a report listing,
// - we're not in the editor view,
// - we're not in the dashboard view,
// and:
// - no bulk actions are present,
// - we're not in the "custom ordering" mode,
// then apply the same 80px padding via the first column's left padding.
&:not(.nice-padding &, .report &, .editor-view &, .w-dashboard &):not(
&:not(.nice-padding &, .report &, .editor-view &):not(
:has(
td:first-child input[type='checkbox']:only-child,
th:first-child input[type='checkbox']:only-child,
td:first-child input[type='checkbox'],
th:first-child input[type='checkbox'],
.ord
)
) {
// stylelint-disable-next-line selector-max-specificity
th:first-child,
td:first-child {
padding-inline-start: theme('spacing.20');

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:map';
@use '../settings' as *;
// Loading mask: overlays a certain area with a loading spinner and a faded out cover to prevent interaction
.loading-mask {
&.loading {

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
// Messages are specific to Django's 'Messaging' system which adds messages into the session,
// for display on the next page visited. These appear as an animated banner at the top of the page.
// For inline help text, see typography.scss
@ -60,10 +58,6 @@
.warning {
background-color: theme('colors.warning.100');
color: theme('colors.grey.600');
@include more-contrast() {
background-color: theme('colors.warning.75');
}
}
.info {

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
$zindex-modal-background: 500;
.fade {

Wyświetl plik

@ -1,6 +1,3 @@
@use '../tools' as *;
@use '../settings' as *;
$header-icon-size: theme('spacing.4');
$header-button-size: theme('spacing.6');
@ -74,8 +71,6 @@ $header-button-size: theme('spacing.6');
width: $header-button-size;
height: $header-button-size;
@include more-contrast-interactive();
&:focus-visible,
&:hover {
color: theme('colors.icon-primary-hover');
@ -165,26 +160,3 @@ $header-button-size: theme('spacing.6');
.w-panel__wrapper {
@include max-form-width();
}
.w-panel--dashboard {
background-color: theme('colors.surface-dashboard-panel');
border: 1px solid theme('colors.border-furniture');
border-radius: 5px;
margin-bottom: calc(
theme('spacing.4') + theme('spacing.4') * var(--w-density-factor)
);
.w-panel__header {
padding: theme('spacing.5');
margin-inline-start: 0;
@include media-breakpoint-up(sm) {
margin-inline-start: calc(-1 * theme('spacing.5'));
}
}
.w-panel__heading {
margin-inline-start: theme('spacing.2');
white-space: wrap;
}
}

Wyświetl plik

@ -1,8 +1,5 @@
@use '../tools' as *;
.w-preview {
.preview-panel {
--w-preview-background-color: var(--w-color-white);
--w-preview-color-scheme: normal;
--preview-width-ratio: min(
1,
var(--preview-panel-width, 450) / var(--preview-device-width, 375)
@ -40,16 +37,6 @@
&:empty {
// Ensure that sites without a background show with a fallback, only when iframe has loaded
background-color: var(--w-preview-background-color);
// Sites that do not have a background but have color-scheme will have the
// colors (background, text, etc.) automatically styled by the browser.
// If the color-scheme matches Wagtail's current color-scheme, the browser
// will give the iframe a transparent background. If we only set the
// white background-color above, the white background will be used
// while the rest of the content follows the color-scheme of the site,
// which might result in white text on a white background.
// Since we cannot know the actual value of the content's color-scheme,
// we set the color-scheme to normal to ensure the iframe stays opaque.
color-scheme: var(--w-preview-color-scheme);
}
[dir='rtl'] & {
@ -72,11 +59,6 @@
gap: 0.75rem;
padding-bottom: 1rem;
margin-bottom: 1rem;
padding-inline: 1rem;
@include more-contrast() {
border-color: theme('colors.border-furniture-more-contrast');
}
}
&__size-button {
@ -91,12 +73,7 @@
place-items: center;
cursor: pointer;
&--selected,
&--selected:hover {
@apply w-bg-surface-menus w-text-text-button w-transform-none w-border w-border-transparent;
}
&:focus-within:has(:focus-visible) {
&:focus-within {
@include focus-outline;
}
@ -112,25 +89,25 @@
@include svg-icon(0.9rem);
}
}
input[type='radio'] {
position: absolute;
width: 0;
height: 0;
opacity: 0;
}
}
&__refresh-button.button--icon {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
position: absolute;
top: 1rem;
width: 2rem;
height: 2rem;
padding: 0;
top: 1.25rem;
inset-inline-end: 1.5rem;
// Use element and class selectors to beat .button-longrunning specificity
svg.icon,
svg.icon-spinner {
margin-inline-end: 0;
width: 1rem;
height: 1rem;
.icon {
@include svg-icon(0.9rem);
}
}
@ -140,6 +117,12 @@
inset-inline-end: 1.5rem;
}
&--mobile &__size-button--mobile,
&--tablet &__size-button--tablet,
&--desktop &__size-button--desktop {
@apply w-bg-surface-menus w-text-text-button w-transform-none w-border w-border-transparent;
}
&__controls {
@apply w-border-t w-border-transparent w-duration-500 w-ease-in-out;
transition-property: border-color, margin-top, padding-top;
@ -148,7 +131,7 @@
// Show the border only if there's an error,
// but always show it if there are multiple preview modes
.w-preview--has-errors &:not(&--multiple),
.preview-panel--has-errors &:not(&--multiple),
&--multiple {
@apply w-border-border-furniture w-border-t;
padding-top: 1rem;
@ -201,22 +184,4 @@
&__mode-select {
@apply w-outline-offset-inside;
}
// A hidden element that is only rendered for functionality purposes,
// but is not visible to the user. Used by radio inputs for preview sizes and
// the iframe while it's loading. We nest the selector rather than suffixing
// the parent selector to beat the specificity of input[type="radio"] styles
.w-preview__proxy {
position: absolute;
width: 0;
height: 0;
opacity: 0;
// Remove mask-image from radio inputs to avoid loading the default icon,
// use extra specificity to beat the default styles
&:is(input[type='radio'])::before {
content: none;
mask-image: none;
}
}
}

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.progress {
border-radius: 1.2em;
background-color: theme('colors.surface-button-hover');

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:color';
@use '../settings' as *;
.w-status {
border-radius: 2px;
@ -20,6 +19,7 @@
&.w-status--primary {
color: theme('colors.text-meta');
border: 1px solid theme('colors.text-meta');
background: theme('colors.surface-page');
}
@ -57,10 +57,8 @@ button.w-status:hover {
color: theme('colors.text-button-outline-hover');
}
// Special case for text-transform: uppercase.
.page-status-tag {
@apply w-inline-flex w-items-center w-justify-center w-whitespace-nowrap w-px-1 w-ml-3 w-text-11 w-rounded-sm w-bg-transparent w-text-text-meta w-border w-border-border-furniture w-no-underline w-font-semibold hover:w-border-surface-menus hover:w-text-text-label w-transition more-contrast:w-border more-contrast:w-border-border-interactive-more-contrast hover:more-contrast:w-border-border-interactive-more-contrast-hover;
// Special case for text-transform: uppercase.
// stylelint-disable-next-line property-disallowed-list
text-transform: uppercase;
}

Wyświetl plik

@ -1,34 +1,69 @@
@use '../tools' as *;
.w-summary {
// set up responsive font size for icon and number as local custom property
--w-summary-item-font-size: clamp(
theme('fontSize.30') * 1.5,
6.5vw,
calc(theme('fontSize.30') * 3)
);
color: theme('colors.text-link-default');
margin-bottom: theme('spacing.3');
padding-top: theme('spacing.1');
margin-bottom: theme('spacing.8');
padding-top: theme('spacing.8');
.w-summary__list {
@include unlist();
display: flex;
flex-wrap: wrap;
column-gap: theme('spacing.8');
justify-content: space-evenly;
width: 100%;
}
/* Summary item */
li {
display: flex;
align-items: center;
flex: 1 1 auto;
flex-wrap: nowrap;
gap: theme('spacing.[2.5]');
margin-bottom: theme('spacing.6');
}
/* Summary icon */
.icon {
@include svg-icon(1.375rem);
color: theme('colors.icon-primary');
font-size: var(--w-summary-item-font-size);
height: 1em;
margin-inline-end: 0.15em;
width: 1em;
}
/* Summary label (a link, use parent colours ) */
a {
text-decoration: underline;
text-underline-offset: 3px;
color: inherit;
text-align: start;
display: inline-flex;
flex-direction: column;
gap: theme('spacing.[1.5]');
@include media-breakpoint-up(sm) {
font-size: theme('fontSize.18');
}
/* Summary big number */
> span {
display: block;
font-size: calc(var(--w-summary-item-font-size) * 0.6);
font-weight: theme('fontWeight.bold');
line-height: 0.9em; // label underneath to come in tight against the number
}
}
}
// Media for Windows High Contrast Mode
@media (forced-colors: active) {
.w-summary {
.icon {
color: LinkText;
opacity: 1;
}
}
}

Wyświetl plik

@ -1,7 +1,4 @@
@use 'sass:map';
@use '../tools' as *;
@use '../settings' as *;
// free tagging tags from taggit
.tag {
border-radius: 2px;
@ -40,16 +37,16 @@ a.tag:hover {
.tagfilter {
legend {
@include media-breakpoint-up(sm) {
@include column(2);
padding-inline-start: 0;
}
font-weight: 700;
color: theme('colors.text-context');
font-size: 1.1em;
display: block;
padding: 0 0 0.8em;
@include media-breakpoint-up(sm) {
@include column(2);
padding-inline-start: 0;
}
}
a {

Wyświetl plik

@ -1,7 +1,6 @@
@use 'sass:map';
@use 'sass:math';
@use 'sass:string';
@use '../tools' as *;
// =============================================================================
// Variables

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.workflow-timeline {
@apply w-label-3;
padding: 0;
@ -43,14 +41,13 @@
position: relative;
flex-shrink: 0;
background: theme('colors.surface-page');
@media (forced-colors: active) {
background: Canvas;
}
margin-inline-end: theme('spacing.[2.5]');
width: theme('spacing.5');
height: theme('spacing.5');
z-index: theme('zIndex.10');
@media (forced-colors: active) {
background: Canvas;
}
}
&__line {

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
@include media-breakpoint-up(sm) {
.browsermessage {
margin: 0 0 0 -150px;

Wyświetl plik

@ -1,5 +1,3 @@
@use '../../settings' as *;
// file drop zones
.drop-zone {
border-radius: 5px;

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:map';
@use '../../settings' as *;
.error-message {
border: 1px solid transparent; // ensure visible separation in Windows High Contrast mode

Wyświetl plik

@ -1,5 +1,4 @@
@use '../../tools' as *;
// Comments
$icon-size: theme('spacing.4');
$button-padding: theme('spacing.2');
@ -54,6 +53,14 @@ $button-padding: theme('spacing.2');
transform: translateY(0);
top: 0;
}
.w-field--date_field &,
.w-field--date_time_field &,
.w-field--time_field & {
position: relative;
transform: translateY(0);
top: 0;
}
}
.w-field__comment-button--add {

Wyświetl plik

@ -1,9 +1,6 @@
@use '../../tools' as *;
.w-field-row {
@include max-form-width();
// Ensure there is enough room for a comment button within the gap.
gap: theme('spacing.7');
gap: theme('spacing.5');
// For mobile viewports, we attempt to display all items in the row side by side even if not at the desired size.
display: flex;
flex-wrap: wrap;

Wyświetl plik

@ -1,6 +1,4 @@
@use 'sass:map';
@use '../../settings' as *;
@use './input-base' as *;
/**
* A container for rendering human-readable field values in forms in a way
@ -8,7 +6,9 @@
*/
.w-field__textoutput {
@include input-base();
@apply w-body-text-large;
background-color: theme('colors.surface-field-inactive');
width: 100%;
padding: theme('spacing.[1.5]') theme('spacing.5');
min-height: $text-input-height;
@ -16,13 +16,6 @@
overflow: hidden;
overflow-wrap: break-word;
@include input-base();
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
& {
background-color: theme('colors.surface-field-inactive');
}
&,
&:hover {
border-color: theme('colors.border-field-inactive');

Wyświetl plik

@ -1,6 +1,4 @@
@use 'sass:map';
@use '../../tools' as *;
@use '../../settings' as *;
/**
* The field component handles form fields layout and ancillary elements such as error messages and help text.

Wyświetl plik

@ -1,6 +1,3 @@
@use '../../tools' as *;
@use '../../settings' as *;
.w-form-width {
@include max-form-width();
}

Wyświetl plik

@ -1,5 +1,3 @@
@use '../../tools' as *;
/**
* Field styles reusable across **all** fields, including:
* Text input, textarea, checkbox, radio, select, etc.
@ -11,8 +9,6 @@
background-color: theme('colors.surface-field');
border: 1px solid theme('colors.border-field-default');
@include more-contrast-interactive();
&:hover {
border-color: theme('colors.border-field-hover');
}

Wyświetl plik

@ -1,6 +1,3 @@
@use '../../settings' as *;
@use './input-base' as *;
// All HTML5 input types, with irrelevant ones commented out.
// input[type="button"],
// input[type="checkbox"],
@ -25,12 +22,11 @@ input[type="time"],
input[type="url"],
input[type="week"],
textarea {
@include input-base();
@apply w-body-text-large;
width: 100%;
padding: theme('spacing.[1.5]') theme('spacing.5');
min-height: $text-input-height;
@include input-base();
}
// Multiline text fields have larger top-bottom padding.
@ -43,15 +39,11 @@ textarea {
resize: none;
}
// Make non-text field types with custom widgets have a smaller width.
.w-field--date_field,
.w-field--date_time_field,
.w-field--time_field {
// Make sure comment buttons are as close as possible.
display: inline-block;
// Make non-text field types with custom widgets have a smaller width.
input {
width: auto;
max-width: 100%;
}
}

Wyświetl plik

@ -1,6 +1,3 @@
@use '../../tools' as *;
@use '../../settings' as *;
$header-icon-size: theme('spacing.4');
$icon-center-offset: 2px;
$guide-line-bottom-margin: calc($form-field-spacing / 3);
@ -21,11 +18,11 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
}
.w-panel__content {
@include guide-line-vertical();
// Center the vertical line.
margin-inline-start: calc(-1 * var(--nesting-indent));
padding-inline-start: var(--nesting-indent);
margin-bottom: $guide-line-bottom-margin;
@include guide-line-vertical();
@include media-breakpoint-up(sm) {
// Extra pixels for better alignment with center of icon.
@ -57,11 +54,10 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
// Styles for nested panels excluding the top level.
.w-panel--nested .w-panel {
@include guide-line-nested();
margin-inline-start: var(--nesting-indent);
margin-bottom: 0;
@include guide-line-nested();
.w-panel__content {
margin-inline-start: calc(
-1 * (var(--nesting-indent) + $icon-center-offset - var(--header-gap) / 2)
@ -84,10 +80,9 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
}
.w-panel__divider {
@include guide-line-horizontal();
// Slightly nicer text alignment.
margin-top: 1px;
@include guide-line-horizontal();
}
.w-panel__heading--label {

Wyświetl plik

@ -7,9 +7,6 @@
.w-field--checkbox_select_multiple_with_disabled_options,
.w-field--boolean_radio_select,
.w-field--radio_select {
// Make sure comment buttons are as close as possible.
display: inline-block;
ul {
list-style: none;
padding: 0;

Wyświetl plik

@ -1,6 +1,4 @@
@use 'sass:math';
@use '../../settings' as *;
@use './input-base' as *;
// 24px input widget size.
$size: 1.5rem;
@ -11,6 +9,7 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
// Both input types are very similar in appearance and layout.
@mixin radio-checkbox-base() {
@include input-base();
display: inline-block;
position: relative;
height: $size;
@ -20,8 +19,6 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
// Prevent the checkbox or radio button from shrinking when the label is long.
flex-shrink: 0;
@include input-base();
&::before {
content: '';
position: absolute;
@ -42,11 +39,8 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
input[type='radio'] {
@include radio-checkbox-base();
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
& {
border-radius: theme('borderRadius.full');
}
display: inline-block;
border-radius: theme('borderRadius.full');
&:checked::before {
mask-image: url('#{$images-root}icons/radio-full.svg');
@ -55,13 +49,9 @@ input[type='radio'] {
input[type='checkbox'] {
@include radio-checkbox-base();
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
& {
border-radius: theme('borderRadius.sm');
// Legacy alignment for checkboxes, particularly within listings.
vertical-align: bottom;
}
border-radius: theme('borderRadius.sm');
// Legacy alignment for checkboxes, particularly within listings.
vertical-align: bottom;
&:checked::before {
mask-image: url('#{$images-root}icons/check.svg');

Wyświetl plik

@ -1,5 +1,3 @@
@use '../../tools' as *;
.w-required-mark {
color: theme('colors.text-error');
margin-inline-start: 0.25ch;

Wyświetl plik

@ -1,7 +1,5 @@
@use 'sass:map';
@use 'sass:math';
@use '../../settings' as *;
@use './input-base' as *;
$select-size: $text-input-height;
$chevron-size: 0.375rem;
@ -38,6 +36,7 @@ $chevron-offset: math.div($select-size - $chevron-size, 2);
}
select {
@include input-base();
@include select-arrow();
@apply w-body-text-large;
// Firefox workaround Set a large line height (but smaller than min height) so the fields text has enough top padding.
@ -48,8 +47,6 @@ select {
// Prevent the element from overflowing the container.
max-width: 100%;
@include input-base();
@media (forced-colors: active) {
appearance: auto;
}
@ -64,8 +61,3 @@ select[multiple] {
padding: 0 theme('spacing.5');
}
}
.w-field--select {
// Make sure comment buttons are as close as possible.
display: inline-block;
}

Wyświetl plik

@ -93,6 +93,12 @@ $switch-border-radius: math.div(($switch-height + $switch-border * 2), 2);
outline: theme('colors.focus') solid $switch-outline;
}
@supports not selector(:focus-visible) {
[type='checkbox']:focus + &__toggle {
outline: theme('colors.focus') solid $switch-outline;
}
}
[type='checkbox'] {
position: absolute;
opacity: 0;

Wyświetl plik

@ -1,5 +1,3 @@
@use './input-base' as *;
.tagit {
@include input-base();

Wyświetl plik

@ -33,22 +33,22 @@ BEM: https://getbem.com/
/* Legacy vendor styles. Do not add new styles here. */
@use 'generic/normalize';
@use 'vendor/jquery-ui-1.10.3.verdant';
@use 'vendor/jquery.tagit' as jquery-tagit;
@use 'vendor/jquery.Jcrop.min' as jquery-jcrop;
@use 'vendor/jquery.tagit' as tagit;
@use 'vendor/jquery.Jcrop.min' as jcrop;
/* SETTINGS
These are variables, maps, and fonts.
* No CSS should be produced by these files
*/
@use 'settings';
@import 'settings';
/* TOOLS
These are functions and mixins.
* No CSS should be produced by these files.
*/
@use 'tools';
@import 'tools';
/* GENERIC
This is for resets and other rules that affect large collections of bare elements.
@ -60,9 +60,14 @@ These are base styles for bare HTML elements.
* Changes to them should be very rare.
*/
@use 'elements/elements';
@use 'elements/typography';
@use 'elements/forms';
// These inject Tailwind's base, component and utility styles and any styles registered by plugins of each layer.
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
@tailwind base;
@tailwind components;
@import 'elements/elements';
@import 'elements/typography';
@import 'elements/forms';
/* COMPONENTS
These are classes for components.
@ -71,87 +76,81 @@ These are classes for components.
which is the preferred pattern over housing them in the scss folder.
*/
@use '../src/components/Transition/Transition';
@use '../src/components/LoadingSpinner/LoadingSpinner';
@use '../src/components/PublicationStatus/PublicationStatus';
@use '../src/components/ComboBox/ComboBox';
@use '../src/components/ComboBoxPreview/ComboBoxPreview';
@use '../src/components/PageExplorer/PageExplorer';
@use '../src/components/CommentApp/main';
@import '../src/components/Transition/Transition';
@import '../src/components/LoadingSpinner/LoadingSpinner';
@import '../src/components/PublicationStatus/PublicationStatus';
@import '../src/components/ComboBox/ComboBox';
@import '../src/components/PageExplorer/PageExplorer';
@import '../src/components/CommentApp/main';
@use 'components/avatar';
@use 'components/icons';
@use 'components/forms/input-base';
@use 'components/forms/input-text';
@use 'components/forms/radio-checkbox';
@use 'components/forms/select';
@use 'components/forms/tagit';
@use 'components/forms/radio-checkbox-multiple';
@use 'components/forms/error-message';
@use 'components/forms/required-mark';
@use 'components/forms/help';
@use 'components/forms/drop-zone';
@use 'components/forms/daterange';
@use 'components/forms/file';
@use 'components/forms/publishing';
@use 'components/forms/switch';
@use 'components/forms/title';
@use 'components/forms/field';
@use 'components/forms/field-row';
@use 'components/forms/field-comment-control';
@use 'components/forms/field-textoutput';
@use 'components/forms/form-width';
@use 'components/forms/nested-panel';
@use 'components/tabs';
@use 'components/panel';
@use 'components/dialog';
@use 'components/dismissible';
@use 'components/drilldown';
@use 'components/dropdown';
@use 'components/dropdown-button';
@use 'components/help-block';
@use 'components/button';
@use 'components/keyboard-shortcuts';
@use 'components/modals';
@use 'components/chooser';
@use 'components/tag';
@use 'components/listing';
@use 'components/filters';
@use 'components/messages';
@use 'components/messages.capability' as messages-capability;
@use 'components/messages.status' as messages-status;
@use 'components/header';
@use 'components/progressbar';
@use 'components/summary';
@use 'components/whats-new';
@use 'components/grid.legacy';
@use 'components/footer';
@use 'components/loading-mask';
@use 'components/human-readable-date';
@use 'components/link.legacy';
@use 'components/indicator';
@use 'components/status-tag';
@use 'components/skiplink';
@use 'components/workflow-tasks';
@use 'components/workflow-timeline';
@use 'components/bulk_actions';
@use 'components/preview-panel';
@use 'components/preview-error';
@use 'components/form-side';
@use 'components/a11y-result';
@use 'components/userbar';
@use 'components/breadcrumbs';
@use 'components/pill';
@use 'components/ping';
@use 'components/editing-sessions';
@import 'components/avatar';
@import 'components/icons';
@import 'components/forms/input-base';
@import 'components/forms/input-text';
@import 'components/forms/radio-checkbox';
@import 'components/forms/select';
@import 'components/forms/tagit';
@import 'components/forms/radio-checkbox-multiple';
@import 'components/forms/error-message';
@import 'components/forms/required-mark';
@import 'components/forms/help';
@import 'components/forms/drop-zone';
@import 'components/forms/daterange';
@import 'components/forms/file';
@import 'components/forms/publishing';
@import 'components/forms/switch';
@import 'components/forms/title';
@import 'components/forms/field';
@import 'components/forms/field-row';
@import 'components/forms/field-comment-control';
@import 'components/forms/field-textoutput';
@import 'components/forms/form-width';
@import 'components/forms/nested-panel';
@import 'components/tabs';
@import 'components/panel';
@import 'components/dialog';
@import 'components/dismissible';
@import 'components/drilldown';
@import 'components/dropdown';
@import 'components/dropdown-button';
@import 'components/help-block';
@import 'components/button';
@import 'components/keyboard-shortcuts';
@import 'components/modals';
@import 'components/chooser';
@import 'components/tag';
@import 'components/listing';
@import 'components/filters';
@import 'components/messages';
@import 'components/messages.capability';
@import 'components/messages.status';
@import 'components/header';
@import 'components/progressbar';
@import 'components/summary';
@import 'components/whats-new';
@import 'components/grid.legacy';
@import 'components/footer';
@import 'components/loading-mask';
@import 'components/human-readable-date';
@import 'components/link.legacy';
@import 'components/indicator';
@import 'components/status-tag';
@import 'components/skiplink';
@import 'components/workflow-tasks';
@import 'components/workflow-timeline';
@import 'components/bulk_actions';
@import 'components/preview-panel';
@import 'components/preview-error';
@import 'components/form-side';
@import 'components/a11y-result';
@import 'components/userbar';
@import 'components/breadcrumbs';
@import 'components/pill';
@import 'components/ping';
@import 'components/editing-sessions';
@use '../src/components/Sidebar/Sidebar';
@use '../src/components/Sidebar/SidebarPanel';
@use '../src/components/Sidebar/menu/MenuItem';
@use '../src/components/Sidebar/menu/SubMenuItem';
@use '../src/components/Sidebar/modules/MainMenu';
@use '../src/components/Sidebar/modules/WagtailBranding';
@use '../src/components/Minimap/Minimap';
@import '../src/components/Sidebar/Sidebar';
@import '../src/components/Minimap/Minimap';
/* OVERRIDES
These are classes that provide overrides.
@ -159,28 +158,30 @@ These are classes that provide overrides.
*/
// VENDOR: overrides of vendor styles.
@use 'overrides/vendor.datetimepicker' as vendor-datetimepicker;
@use 'overrides/vendor.handsontable' as vendor-handsontable;
@use 'overrides/vendor.tagit' as vendor-tagit;
@use 'overrides/vendor.tippy' as vendor-tippy;
@import 'overrides/vendor.datetimepicker';
@import 'overrides/vendor.handsontable';
@import 'overrides/vendor.tagit';
@import 'overrides/vendor.tippy';
// UTILITIES: classes that do one simple thing.
@use 'overrides/utilities.focus' as utilities-focus;
@import 'overrides/utilities.focus';
// Legacy utilities
@use 'overrides/utilities.legacy' as utilities-legacy;
@import 'overrides/utilities.legacy';
// TAILWIND: This is at the bottom so it can take precedence over other css classes
@use 'overrides/utilities.tailwind' as utilities-tailwind;
@tailwind utilities;
/* Legacy layout-specific styles. Do not add new styles here. */
@use 'layouts/404' as layout-404;
@use 'layouts/compare-revisions';
@use 'layouts/login';
@use 'layouts/account';
@use 'layouts/workflow-progress';
@use 'layouts/report';
@use 'layouts/add-multiple';
@use 'layouts/chooser-duplicate-upload';
@use 'layouts/focal-point-chooser';
@use 'layouts/redirects';
@import 'layouts/404';
@import 'layouts/compare-revisions';
@import 'layouts/home';
@import 'layouts/login';
@import 'layouts/account';
@import 'layouts/workflow-progress';
@import 'layouts/report';
@import 'layouts/add-multiple';
@import 'layouts/chooser-duplicate-upload';
@import 'layouts/focal-point-chooser';
@import 'layouts/redirects';

Wyświetl plik

@ -1,10 +1,3 @@
// These inject Tailwind's base and component styles and any styles registered by plugins of each layer.
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
@tailwind base;
@tailwind components;
*,
::before,
::after {

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:map';
@use '../tools' as *;
// Legacy form reset styles. Avoid adding any new styles here.
form {
// Historically, Wagtail forms rendered all fields as list items.

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.page404__bg {
position: fixed;
top: 0;

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
$color-addition-dark: var(--color-addition-dark);
$color-addition-light: var(--color-addition-light);
$color-deletion-dark: var(--color-deletion-dark);

Wyświetl plik

@ -1,5 +1,3 @@
@use '../tools' as *;
.focal-point-chooser {
position: relative;
margin-bottom: 20px;

Wyświetl plik

@ -0,0 +1,10 @@
.homepage {
.listing tbody {
border-bottom: 0;
}
.task .icon {
// pull out the icon so it aligns with no-icon text
margin-inline-start: -1.75em;
}
}

Wyświetl plik

@ -1,19 +1,30 @@
@use '../tools' as *;
@mixin login-fullscreen-background() {
@at-root {
:root {
--w-login-fullscreen-background: radial-gradient(
100% 300.28% at 100% 0%,
theme('colors.primary.DEFAULT') 0%,
theme('colors.primary.DEFAULT') 32.94%,
theme('colors.primary.DEFAULT') 49.9%,
theme('colors.primary.DEFAULT') 50.2%,
theme('colors.secondary.DEFAULT') 100%
);
}
}
:root {
--w-login-fullscreen-background: radial-gradient(
100% 300.28% at 100% 0%,
theme('colors.primary.DEFAULT') 0%,
theme('colors.primary.DEFAULT') 32.94%,
theme('colors.primary.DEFAULT') 49.9%,
theme('colors.primary.DEFAULT') 50.2%,
theme('colors.secondary.DEFAULT') 100%
// support older browsers that do not support radial gradient 'at' usage
background: theme('colors.surface-menus');
/* stylelint-disable-next-line declaration-block-no-duplicate-properties */
background: var(
--w-login-fullscreen-background,
theme('colors.primary.DEFAULT')
);
}
.login {
@include login-fullscreen-background;
color: theme('colors.text-label');
background: var(--w-login-fullscreen-background);
.wrapper {
align-items: center;

Wyświetl plik

@ -1,11 +1,8 @@
@use '../tools' as *;
.report {
@include nice-margin();
display: grid;
grid-column-gap: theme('spacing.12');
@include nice-margin();
&__results {
&--text {
margin: 0 theme('spacing.[1.5]') theme('spacing.[1.5]') 0;

Wyświetl plik

@ -1,9 +1,16 @@
@use '../settings' as *;
// stylelint-disable declaration-no-important
// Set global focus outline styles so they are consistent across the UI,
// without individual components having to explicitly define focus styles.
// Using !important because we want to enforce only one style is used across the UI.
// Remove :focus selectors once we stop supporting Safari 15.4.
*:focus {
outline: $focus-outline-width solid theme('colors.focus') !important;
}
*:focus:not(:focus-visible) {
outline: none !important;
}
*:focus-visible {
outline: $focus-outline-width solid theme('colors.focus') !important;
}

Wyświetl plik

@ -1,6 +1,3 @@
@use '../tools' as *;
@use '../settings' as *;
.nice-padding {
padding-inline-start: $mobile-nice-padding;
padding-inline-end: $mobile-nice-padding;

Wyświetl plik

@ -1 +0,0 @@
@tailwind utilities;

Wyświetl plik

@ -1,6 +1,5 @@
// stylelint-disable selector-max-combinators, max-nesting-depth
@use 'sass:map';
@use '../settings' as *;
.xdsoft_datetimepicker {
box-shadow: 0 5px 10px -5px theme('colors.black-35');

Wyświetl plik

@ -1,5 +1,4 @@
@use 'sass:map';
@use '../settings' as *;
// taggit tagging
.tagit {

Wyświetl plik

@ -1,5 +1,5 @@
// stylelint-disable selector-attribute-name-disallowed-list
@use '../../../node_modules/tippy.js/dist/tippy';
@import '../../../node_modules/tippy.js/dist/tippy';
.tippy-box {
// Special font size 12px for tooltips

Wyświetl plik

@ -1,6 +1,5 @@
@use 'sass:list';
@use 'sass:map';
@use '../settings' as *;
// Based upon the fine work and thoughts from Bootstrap v4.
// Copyright 2011-2018 The Bootstrap Authors
// Copyright 2011-2018 Twitter, Inc.

Wyświetl plik

@ -1,5 +1,3 @@
@use 'functions.breakpoints' as *;
// Based upon the fine work and thoughts from Bootstrap v4.
// Copyright 2011-2018 The Bootstrap Authors
// Copyright 2011-2018 Twitter, Inc.

Wyświetl plik

@ -4,8 +4,6 @@
// Please note that the mixins partial shouldn't include any classes. This is so
// it can be included in any file without accidentally producing output
@use '../settings' as *;
// Turns on font-smoothing when used. Use sparingly.
@mixin font-smoothing {
-webkit-font-smoothing: antialiased;
@ -95,21 +93,6 @@
}
}
/**
* Apply styles for enhanced contrast theming.
*/
@mixin more-contrast() {
.w-contrast-more & {
@content;
}
@media (prefers-contrast: more) {
.w-contrast-system & {
@content;
}
}
}
/**
* Apply styles for the light theme only.
*/
@ -124,52 +107,3 @@
}
}
}
/**
* Apply styles for the dark theme with increased contrast.
*/
@mixin dark-theme-more-contrast() {
.w-theme-dark.w-contrast-more & {
@content;
}
@media (prefers-color-scheme: dark) {
.w-theme-system.w-contrast-more & {
@content;
}
}
@media (prefers-contrast: more) {
.w-theme-dark.w-contrast-system & {
@content;
}
}
@media (prefers-color-scheme: dark) and (prefers-contrast: more) {
.w-theme-system.w-contrast-system & {
@content;
}
}
}
/**
* Increased contrast theme styles for interactive components
*/
@mixin more-contrast-interactive() {
@include more-contrast() {
border: 1px solid theme('colors.border-interactive-more-contrast');
&:hover {
border-color: theme('colors.border-interactive-more-contrast-hover');
}
&[disabled],
&[disabled]:hover {
border-style: dashed;
}
}
}
@mixin focus-outline {
outline: $focus-outline-width solid theme('colors.focus');
}

Wyświetl plik

@ -1,7 +1,4 @@
@use 'sass:math';
@use '../settings' as *;
@use '../tools/mixins.breakpoints' as *;
@use '../tools/mixins.general' as *;
// grid settings
$grid-columns: 12;

Wyświetl plik

@ -1,9 +1,7 @@
import { WAGTAIL_CONFIG } from '../config/wagtailConfig';
import { ADMIN_API } from '../config/wagtailConfig';
import { getPageChildren, getPage } from './admin';
import client from './client';
const { ADMIN_API } = WAGTAIL_CONFIG;
jest.mock('./client', () => {
const stubResult = {
__types: {

Wyświetl plik

@ -1,8 +1,6 @@
import client from './client';
import { WAGTAIL_CONFIG } from '../config/wagtailConfig';
const { ADMIN_API } = WAGTAIL_CONFIG;
import { ADMIN_API } from '../config/wagtailConfig';
export interface WagtailPageAPI {
id: number;

Wyświetl plik

@ -14,11 +14,8 @@ const checkStatus = (response) => {
const parseJSON = (response) => response.json();
/**
* Response timeout cancelling the promise (not the request).
*
* @see https://github.com/github/fetch/issues/175#issuecomment-216791333.
*/
// Response timeout cancelling the promise (not the request).
// See https://github.com/github/fetch/issues/175#issuecomment-216791333.
const timeout = (ms, promise) => {
const race = new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
@ -41,7 +38,7 @@ const timeout = (ms, promise) => {
};
/**
* Wrapper around fetch with sane defaults for behavior in the face of
* Wrapper around fetch with sane defaults for behaviour in the face of
* errors.
*/
const request = (method, url) => {

Wyświetl plik

@ -1,13 +1,13 @@
/* global DocumentChooserModal */
import { Chooser, ChooserFactory } from '.';
export class DocumentChooser extends Chooser {
// eslint-disable-next-line no-undef
chooserModalClass = DocumentChooserModal;
}
window.DocumentChooser = DocumentChooser;
export class DocumentChooserFactory extends ChooserFactory {
widgetClass = DocumentChooser;
// eslint-disable-next-line no-undef
chooserModalClass = DocumentChooserModal;
}

Wyświetl plik

@ -1,8 +1,7 @@
/* global ImageChooserModal */
import { Chooser, ChooserFactory } from '.';
export class ImageChooser extends Chooser {
// eslint-disable-next-line no-undef
chooserModalClass = ImageChooserModal;
initHTMLElements(id) {
@ -12,21 +11,12 @@ export class ImageChooser extends Chooser {
);
}
/**
* Constructs the initial state of the chooser from the rendered (static) HTML.
* The state is either null (no image chosen) or an object containing the image details.
*
* @returns {Object|null} The initial state of the chooser. If an image is chosen,
* the state object contains the following properties:
* - id: {number} The ID of the chosen image.
* - edit_url: {string} The URL to edit the chosen image.
* - title: {string} The title of the chosen image.
* - preview: {Object} An object containing the preview details of the chosen image:
* - url: {string} The URL of the preview image.
* - width: {string} The width of the preview image.
* - height: {string} The height of the preview image.
*/
getStateFromHTML() {
/*
Construct initial state of the chooser from the rendered (static) HTML.
State is either null (= no image chosen) or a dict of id, edit_url, title
and preview (= a dict of url, width, height).
*/
const state = super.getStateFromHTML();
if (state) {
state.preview = {
@ -34,9 +24,6 @@ export class ImageChooser extends Chooser {
width: this.previewImage.getAttribute('width'),
height: this.previewImage.getAttribute('height'),
};
state.default_alt_text = this.previewImage.getAttribute(
'data-default-alt-text',
);
}
return state;
}
@ -45,14 +32,11 @@ export class ImageChooser extends Chooser {
super.renderState(newState);
this.previewImage.setAttribute('src', newState.preview.url);
this.previewImage.setAttribute('width', newState.preview.width);
this.previewImage.setAttribute(
'data-default-alt-text',
newState.default_alt_text,
);
}
}
export class ImageChooserFactory extends ChooserFactory {
widgetClass = ImageChooser;
// eslint-disable-next-line no-undef
chooserModalClass = ImageChooserModal;
}

Wyświetl plik

@ -1,8 +1,7 @@
/* global PageChooserModal */
import { Chooser, ChooserFactory } from '.';
export class PageChooser extends Chooser {
// eslint-disable-next-line no-undef
chooserModalClass = PageChooserModal;
titleStateKey = 'adminTitle';
@ -45,6 +44,7 @@ export class PageChooser extends Chooser {
export class PageChooserFactory extends ChooserFactory {
widgetClass = PageChooser;
// eslint-disable-next-line no-undef
chooserModalClass = PageChooserModal;
getModalOptions() {

Wyświetl plik

@ -1,16 +1,17 @@
import { ChooserModal } from '../../includes/chooserModal';
import { Chooser, ChooserFactory } from '.';
import { WAGTAIL_CONFIG } from '../../config/wagtailConfig';
/* global wagtailConfig */
class SnippetChooserModal extends ChooserModal {
getURLParams(opts) {
const params = super.getURLParams(opts);
if (WAGTAIL_CONFIG.ACTIVE_CONTENT_LOCALE) {
if (wagtailConfig.ACTIVE_CONTENT_LOCALE) {
// The user is editing a piece of translated content.
// Pass the locale along as a request parameter. If this
// snippet is also translatable, the results will be
// pre-filtered by this locale.
params.locale = WAGTAIL_CONFIG.ACTIVE_CONTENT_LOCALE;
params.locale = wagtailConfig.ACTIVE_CONTENT_LOCALE;
}
return params;
}

Wyświetl plik

@ -1,13 +1,11 @@
import EventEmitter from 'events';
import { ChooserModal } from '../../includes/chooserModal';
export class Chooser extends EventEmitter {
export class Chooser {
chooserModalClass = ChooserModal;
titleStateKey = 'title'; // key used in the 'state' dictionary to hold the human-readable title
editUrlStateKey = 'edit_url'; // key used in the 'state' dictionary to hold the URL of the edit page
constructor(id, opts = {}) {
super();
this.opts = opts;
this.initHTMLElements(id);
this.state = this.getStateFromHTML();
@ -85,7 +83,6 @@ export class Chooser extends EventEmitter {
setStateFromModalData(data) {
this.setState(data);
this.emit('chosen', data);
}
clear() {
@ -213,10 +210,8 @@ export class ChooserFactory {
this.modal.open(options, callback);
}
/**
* retrieve the widget object corresponding to the given HTML ID
*/
getById(id) {
/* retrieve the widget object corresponding to the given HTML ID */
return document.getElementById(`${id}-chooser`).widget;
}
}

Wyświetl plik

@ -1,70 +1,24 @@
@use '../../../scss/tools' as *;
// Ensure consistent spacing across the whole component.
// With the scrolling and show/hide of the field, correct spacing is critical.
$spacing: theme('spacing.[2.5]');
$spacing-sm: theme('spacing.4');
$width: clamp(300px, 75vw, 1000px);
.w-combobox-container {
background: theme('colors.surface-page');
color: theme('colors.text-context');
border-radius: theme('borderRadius.DEFAULT');
box-shadow: theme('boxShadow.md');
outline: 10px solid transparent;
// Use a single column grid on smaller screens,
// and two columns on larger screens.
display: grid;
grid-template-columns: 1fr;
// Case 1: base case
// Use max-content width to minimize shifting due to content wrapping,
// constraining width to 75% of viewport for devices above 400px width.
width: max-content;
max-width: max(300px, 75vw);
@include media-breakpoint-up(md) {
grid-template-columns: min(400px, 80vw) 1fr;
}
@include media-breakpoint-up(lg) {
grid-template-columns: min(512px, 80vw) 1fr;
}
// Case 2: there's a previewable block, but the preview may or may not be active
// On smaller screens, the preview will be shown below. We don't want the
// combobox to change width when the preview is shown or hidden (e.g. due to
// a long description), so set a fixed width. It's OK that this will take up
// more than the necessary width for the combobox, as we know it's not going
// to be wider than 75% of the small screen anyway.
&:has(.w-combobox__option-preview) {
width: $width;
@include media-breakpoint-up(md) {
// On medium-up screens, the preview will be shown to the right. Revert
// the width back to max-content so it doesn't take up the whole `$width`
// when the preview is not active.
width: max-content;
}
}
// Case 3: the preview is currently active
&:has(.w-combobox-preview) {
@include media-breakpoint-up(md) {
// On larger screens, use the fixed `$width` so the width doesn't change
// for different blocks, which may have different description lengths.
width: $width;
}
}
$spacing-sm: theme('spacing.5');
.w-combobox {
width: min(400px, 80vw);
@include dark-theme() {
background-color: theme('colors.surface-tooltip');
}
background: theme('colors.surface-page');
color: theme('colors.text-context');
border-radius: theme('borderRadius.DEFAULT');
font-size: theme('fontSize.18');
box-shadow: theme('boxShadow.md');
outline: 10px solid transparent;
}
.w-combobox__field {
padding: $spacing;
padding-bottom: 0;
font-size: theme('fontSize.18');
@include media-breakpoint-up(sm) {
padding: $spacing-sm;
@ -89,13 +43,12 @@ $width: clamp(300px, 75vw, 1000px);
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: column;
gap: theme('spacing.1');
gap: theme('spacing.[0.5]');
padding: $spacing;
padding-top: 0;
@include media-breakpoint-up(sm) {
width: 100%;
column-gap: theme('spacing.5');
width: 400px;
padding: $spacing-sm;
padding-top: 0;
}
@ -117,63 +70,21 @@ $width: clamp(300px, 75vw, 1000px);
}
}
.w-combobox__option-row {
display: grid;
grid-template-columns: 1fr theme('spacing.6');
}
.w-combobox__option-preview {
@include show-focus-outline-inside();
color: theme('colors.icon-secondary');
background: none;
border: 1px solid transparent;
padding: 0;
width: 100%;
@include more-contrast-interactive();
.icon {
width: theme('spacing.3');
height: theme('spacing.3');
}
&:hover {
color: theme('colors.icon-secondary-hover');
}
&[aria-expanded='true'] {
color: theme('colors.text-link-default');
@media (forced-colors: active) {
background: Highlight;
color: HighlightText;
}
}
}
.w-combobox__option-row--col1 {
grid-column: 1 / span 1;
}
.w-combobox__option-row--col2 {
grid-column: 2 / span 1;
}
.w-combobox__option {
display: grid;
grid-template-columns: theme('spacing.8') 1fr;
align-items: center;
padding: theme('spacing.[2.5]');
border: 1px dotted theme('colors.border-button-small-outline-default');
padding: theme('spacing.2');
border: 1px solid transparent;
font-size: 0.875rem;
line-height: theme('lineHeight.tight');
border-radius: theme('borderRadius.sm');
cursor: pointer;
&[aria-selected='true'] {
border-color: theme('colors.border-button-outline-default');
color: theme('colors.text-link-default');
background: transparent;
cursor: pointer;
@media (forced-colors: active) {
background: Highlight;
@ -182,6 +93,14 @@ $width: clamp(300px, 75vw, 1000px);
}
}
.w-combobox__option--col1 {
grid-column: 1 / span 1;
}
.w-combobox__option--col2 {
grid-column: 2 / span 1;
}
.w-combobox__option-icon {
color: theme('colors.icon-secondary');
height: theme('spacing.4');

Wyświetl plik

@ -40,13 +40,12 @@ describe('ComboBox', () => {
{
type: 'paragraph',
description: 'Paragraph',
icon: <span className="my-icon">P</span>,
icon: <span className="custom-icon">P</span>,
},
{
type: 'heading-one',
label: 'H1',
description: 'Heading 1',
icon: ['M 83.625 ', 'L 232.535156 '],
},
{
type: 'heading-two',
@ -71,10 +70,6 @@ describe('ComboBox', () => {
wrapper = shallow(<ComboBox {...testProps} items={items} />);
});
it('matches the snapshot', () => {
expect(wrapper).toMatchSnapshot();
});
it('shows items', () => {
const options = wrapper.find('.w-combobox__option-text');
expect(options).toHaveLength(
@ -87,24 +82,8 @@ describe('ComboBox', () => {
expect(wrapper.find(Icon).at(0).prop('name')).toBe('blockquote');
});
it('supports custom icons (as provided React component)', () => {
const paragraphOption = wrapper.findWhere(
(el) => el.key() === 'paragraph',
);
const icon = paragraphOption.find('.w-combobox__option-icon').render();
expect(icon.find('.my-icon')).toHaveLength(1);
expect(icon.text()).toBe('P');
});
it('supports custom icons (as provided path)', () => {
const paragraphOption = wrapper.findWhere(
(el) => el.key() === 'heading-one',
);
const icon = paragraphOption.find('.w-combobox__option-icon').render();
expect(icon.find('svg').hasClass('icon-custom')).toBe(true);
expect(icon.find('.icon-custom').html()).toContain('M 83.625');
it('supports custom icons', () => {
expect(wrapper.find('.custom-icon').text()).toBe('P');
});
it('supports label as icon', () => {
@ -113,8 +92,8 @@ describe('ComboBox', () => {
it('combines two categories into one, with two columns', () => {
expect(wrapper.find('.w-combobox__optgroup-label')).toHaveLength(1);
expect(wrapper.find('.w-combobox__option-row--col1')).toHaveLength(3);
expect(wrapper.find('.w-combobox__option-row--col2')).toHaveLength(2);
expect(wrapper.find('.w-combobox__option--col1')).toHaveLength(3);
expect(wrapper.find('.w-combobox__option--col2')).toHaveLength(2);
});
});
});

Wyświetl plik

@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
import { useCombobox, UseComboboxStateChange } from 'downshift';
import { gettext } from '../../utils/gettext';
import ComboBoxPreview from '../ComboBoxPreview/ComboBoxPreview';
import Icon from '../Icon/Icon';
import findMatches from './findMatches';
@ -10,7 +9,6 @@ import findMatches from './findMatches';
export const comboBoxTriggerLabel = gettext('Insert a block');
export const comboBoxLabel = gettext('Search options…');
export const comboBoxNoResults = gettext('No results');
const comboBoxPreviewLabel = gettext('Preview');
export interface ComboBoxCategory<ItemType> {
type: string;
@ -23,8 +21,6 @@ export interface ComboBoxItem {
label?: string | null;
description?: string | null;
icon?: string | JSX.Element | null;
blockDefId?: string;
isPreviewable?: boolean;
category?: string;
render?: (props: { option: ComboBoxItem }) => JSX.Element | string;
}
@ -68,7 +64,6 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
(category) => category.items || [],
);
const [inputItems, setInputItems] = useState<ComboBoxOption[]>(flatItems);
const [previewedIndex, setPreviewedIndex] = useState<number>(-1);
// Re-create the categories so the two-column layout flows as expected.
const categories = items.reduce<ComboBoxCategory<ComboBoxOption>[]>(
(cats, cat, index) => {
@ -119,10 +114,8 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
}
},
/**
* For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
* to switch windows.
*/
// For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
// to switch windows.
stateReducer: (state, actionAndChanges) => {
const { type, changes } = actionAndChanges;
switch (type) {
@ -139,9 +132,6 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
},
onInputValueChange: (changes) => {
// Hide any preview when the user types or clears the search input.
setPreviewedIndex(-1);
const { inputValue: val } = changes;
if (!val) {
setInputItems(flatItems);
@ -178,129 +168,86 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
}
}, [inputValue]);
const previewedBlock =
previewedIndex >= 0 ? inputItems[previewedIndex] : null;
return (
<div className="w-combobox-container">
<div className="w-combobox">
{/* downshift does the label-field association itself. */}
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label {...getLabelProps()} className="w-sr-only">
{label}
</label>
<div className="w-combobox__field">
<input
{...getInputProps()}
type="text"
// Prevent the field from receiving focus if its not visible.
disabled={inlineCombobox}
placeholder={placeholder}
/>
</div>
{noResults ? (
<div className="w-combobox__status">{noResultsText}</div>
) : null}
<div {...getMenuProps()} className="w-combobox__menu">
{categories.map((category) => {
const categoryItems = (category.items || []).filter((item) =>
inputItems.find((i) => i.type === item.type),
);
const itemColumns = Math.ceil(categoryItems.length / 2);
if (categoryItems.length === 0) {
return null;
}
return (
<div className="w-combobox__optgroup" key={category.type}>
{category.label ? (
<div className="w-combobox__optgroup-label">
{category.label}
</div>
) : null}
{categoryItems.map((item, index) => {
const itemLabel = getItemLabel(item.type, item);
const description = getItemDescription(item);
const itemIndex = inputItems.findIndex(
(i) => i.type === item.type,
);
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
const hasIcon =
typeof item.icon !== 'undefined' && item.icon !== null;
let icon: JSX.Element | null | undefined = null;
if (hasIcon) {
if (Array.isArray(item.icon)) {
icon = (
<Icon name="custom" viewBox="0 0 1024 1024">
{item.icon.map((pathData: string) => (
<path key={pathData} d={pathData} />
))}
</Icon>
);
} else {
icon =
typeof item.icon === 'string' ? (
<Icon name={item.icon} />
) : (
item.icon
);
}
}
return (
<div
key={item.type}
className={`w-combobox__option-row w-combobox__option-row--col${itemColumn}`}
>
<div
{...getItemProps({ item, index: itemIndex })}
className="w-combobox__option"
>
<div className="w-combobox__option-icon">
{icon}
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
{itemLabel && !hasIcon ? (
<span>{itemLabel}</span>
) : null}
</div>
<div className="w-combobox__option-text">
{item.render
? item.render({ option: item })
: description}
</div>
</div>
{item.isPreviewable ? (
<button
className="w-combobox__option-preview"
aria-label={comboBoxPreviewLabel}
aria-expanded={previewedIndex === itemIndex}
type="button"
onClick={() =>
setPreviewedIndex(
previewedIndex === itemIndex ? -1 : itemIndex,
)
}
>
<Icon name="view" />
</button>
) : null}
</div>
);
})}
</div>
);
})}
</div>
</div>
{previewedBlock?.isPreviewable ? (
<ComboBoxPreview
item={previewedBlock}
previewLabel={comboBoxPreviewLabel}
<div className="w-combobox">
{/* downshift does the label-field association itself. */}
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label {...getLabelProps()} className="w-sr-only">
{label}
</label>
<div className="w-combobox__field">
<input
{...getInputProps()}
type="text"
// Prevent the field from receiving focus if its not visible.
disabled={inlineCombobox}
placeholder={placeholder}
/>
</div>
{noResults ? (
<div className="w-combobox__status">{noResultsText}</div>
) : null}
<div {...getMenuProps()} className="w-combobox__menu">
{categories.map((category) => {
const categoryItems = (category.items || []).filter((item) =>
inputItems.find((i) => i.type === item.type),
);
const itemColumns = Math.ceil(categoryItems.length / 2);
if (categoryItems.length === 0) {
return null;
}
return (
<div className="w-combobox__optgroup" key={category.type}>
{category.label ? (
<div className="w-combobox__optgroup-label">
{category.label}
</div>
) : null}
{categoryItems.map((item, index) => {
const itemLabel = getItemLabel(item.type, item);
const description = getItemDescription(item);
const itemIndex = inputItems.findIndex(
(i) => i.type === item.type,
);
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
const hasIcon =
typeof item.icon !== 'undefined' && item.icon !== null;
let icon: JSX.Element | null | undefined = null;
if (hasIcon) {
icon =
typeof item.icon === 'string' ? (
<Icon name={item.icon} />
) : (
item.icon
);
}
return (
<div
key={item.type}
{...getItemProps({ item, index: itemIndex })}
className={`w-combobox__option w-combobox__option--col${itemColumn}`}
>
<div className="w-combobox__option-icon">
{icon}
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
{itemLabel && !hasIcon ? <span>{itemLabel}</span> : null}
</div>
<div className="w-combobox__option-text">
{item.render
? item.render({ option: item })
: description}
</div>
</div>
);
})}
</div>
);
})}
</div>
</div>
);
}

Wyświetl plik

@ -1,215 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ComboBox rendering matches the snapshot 1`] = `
<div
className="w-combobox-container"
>
<div
className="w-combobox"
>
<label
className="w-sr-only"
htmlFor="downshift-1-input"
id="downshift-1-label"
>
Search options…
</label>
<div
className="w-combobox__field"
>
<input
aria-activedescendant=""
aria-autocomplete="list"
aria-controls="downshift-1-menu"
aria-expanded={false}
aria-labelledby="downshift-1-label"
autoComplete="off"
disabled={false}
id="downshift-1-input"
onBlur={[Function]}
onChange={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
placeholder="Search options…"
role="combobox"
type="text"
value=""
/>
</div>
<div
aria-labelledby="downshift-1-label"
className="w-combobox__menu"
id="downshift-1-menu"
onMouseLeave={[Function]}
role="listbox"
>
<div
className="w-combobox__optgroup"
key="blockTypes"
>
<div
className="w-combobox__optgroup-label"
>
Blocks
</div>
<div
className="w-combobox__option-row w-combobox__option-row--col1"
key="blockquote"
>
<div
aria-disabled={false}
aria-selected={false}
className="w-combobox__option"
id="downshift-1-item-0"
onClick={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="option"
>
<div
className="w-combobox__option-icon"
>
<Icon
name="blockquote"
/>
</div>
<div
className="w-combobox__option-text"
>
Blockquote
</div>
</div>
</div>
<div
className="w-combobox__option-row w-combobox__option-row--col1"
key="paragraph"
>
<div
aria-disabled={false}
aria-selected={false}
className="w-combobox__option"
id="downshift-1-item-1"
onClick={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="option"
>
<div
className="w-combobox__option-icon"
>
<span
className="my-icon"
>
P
</span>
</div>
<div
className="w-combobox__option-text"
>
Paragraph
</div>
</div>
</div>
<div
className="w-combobox__option-row w-combobox__option-row--col1"
key="heading-one"
>
<div
aria-disabled={false}
aria-selected={false}
className="w-combobox__option"
id="downshift-1-item-2"
onClick={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="option"
>
<div
className="w-combobox__option-icon"
>
<Icon
name="custom"
viewBox="0 0 1024 1024"
>
<path
d="M 83.625 "
key="M 83.625 "
/>
<path
d="L 232.535156 "
key="L 232.535156 "
/>
</Icon>
</div>
<div
className="w-combobox__option-text"
>
Heading 1
</div>
</div>
</div>
<div
className="w-combobox__option-row w-combobox__option-row--col2"
key="heading-two"
>
<div
aria-disabled={false}
aria-selected={false}
className="w-combobox__option"
id="downshift-1-item-3"
onClick={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="option"
>
<div
className="w-combobox__option-icon"
>
<span>
H2
</span>
</div>
<div
className="w-combobox__option-text"
>
<span
className="custom-text"
>
H2
</span>
</div>
</div>
</div>
<div
className="w-combobox__option-row w-combobox__option-row--col2"
key="link"
>
<div
aria-disabled={false}
aria-selected={false}
className="w-combobox__option"
id="downshift-1-item-4"
onClick={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="option"
>
<div
className="w-combobox__option-icon"
>
<span>
🔗
</span>
</div>
<div
className="w-combobox__option-text"
>
Link
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

Wyświetl plik

@ -1,59 +0,0 @@
@use '../../../scss/tools' as *;
.w-combobox-preview {
padding: theme('spacing.5');
display: flex;
flex-direction: column;
gap: theme('spacing.5');
// Set a min-height to ensure it's big enough to be useful
min-height: 400px;
background-color: theme('colors.surface-header');
border-block-start: 1px solid theme('colors.border-furniture');
border-end-end-radius: inherit;
border-end-start-radius: inherit;
@include media-breakpoint-up(md) {
border-block-start: 0;
border-start-end-radius: inherit;
border-end-start-radius: 0;
border-inline-start: 1px solid theme('colors.border-furniture');
}
}
.w-combobox-preview__iframe {
// Take up remaining space
width: 100%;
height: 100%;
border: 1px solid theme('colors.border-furniture');
border-radius: theme('borderRadius.sm');
// Ensure iframe is always opaque
color-scheme: normal;
background-color: Canvas;
@include more-contrast() {
border-color: theme('colors.border-furniture-more-contrast');
}
}
.w-combobox-preview__details {
overflow: hidden;
display: flex;
flex-direction: column;
// Use 65:35 ratio between the iframe and the details, but allow the details
// to grow to a minimum of 100px in case the container is very small
// (i.e. when there are only a few blocks)
min-height: max(35%, 100px);
}
.w-combobox-preview__label {
@apply w-label-1;
}
.w-combobox-preview__description {
@apply w-help-text;
margin-top: theme('spacing.3');
margin-bottom: 0;
overflow: auto;
min-height: 0;
}

Some files were not shown because too many files have changed in this diff Show More