Porównaj commity

...

31 Commity

Autor SHA1 Wiadomość Data
elhussein 062929d454
Merge af86986a16 into 196cb02d10 2024-05-02 09:35:47 +00:00
Matt Westcott 196cb02d10 Generate new strings for translation 2024-05-02 10:06:13 +01:00
Matt Westcott 1874350fbf Update latest.txt for 6.1 / 5.2.5 2024-05-02 09:46:31 +01:00
Storm Heg 2031eb3d24
Give translators more context about how density is used (#11918) 2024-05-02 09:44:53 +01:00
Matt Westcott 4ac42a723f Release note for CopyView fix (cherry-picked from e3d9233f4d) 2024-05-01 13:37:39 +01:00
Matt Westcott ef57f9b2c9 Fill in release date for 6.1 final 2024-05-01 12:41:22 +01:00
Matt Westcott 955703fba6 Fill in release date for 6.0.3 2024-05-01 12:40:43 +01:00
Matt Westcott 42b7c9bcde Release note for CVE-2024-32882 in 6.1 2024-05-01 12:20:00 +01:00
Matt Westcott 9d24ac4e39 Release note for CVE-2024-32882 in 6.0.3 2024-05-01 12:18:47 +01:00
Jake Howard ee57f6d4dc
Merge pull request from GHSA-w2v8-php4-p8hc
* Pass user to settings form to enable permissions checks

* Add tests for settings creation and editing

* Ensure all generic create / edit view forms receive `for_user`

Co-authored-by: Sage Abdullah <sage.abdullah@torchbox.com>

* Test field permissions on ModelViewTest

---------

Co-authored-by: Sage Abdullah <sage.abdullah@torchbox.com>
2024-05-01 12:14:16 +01:00
Matt Westcott 932402fd28 Fetch new translations from Transifex 2024-05-01 11:32:29 +01:00
Matt Westcott 7de6872277 Release note for #11912 in 6.1 2024-05-01 11:20:58 +01:00
Matt Westcott 95d23fdf7d Typo - this features -> these features 2024-05-01 11:20:58 +01:00
Matt Westcott 72edc09851 Release note for #11912 in 6.0.3 2024-05-01 11:20:58 +01:00
Matt Westcott fac768c076 Fill in release date for 5.2.5 2024-05-01 11:20:58 +01:00
Matt Westcott 81a11d63c6 Release note for #11912 in 5.2.5 2024-05-01 11:20:58 +01:00
Matt Westcott 617e5129c5
Add management command to fix UUID fields under MariaDB / Django 5.0 (#11912) 2024-05-01 11:07:20 +01:00
Thibaud Colas cae0002afe Add more sections to 6.1 release notes 2024-04-30 17:29:18 +01:00
Sage Abdullah 08ee15a358 Remove --inline-actions variant of listing tables
This was added in f322e9d868, when the
snippets listing view was briefly redesigned to put the "Edit", "Delete"
etc. actions in the same line as the title instead of in a new line.

With the universal listings design, all listing actions are put inside a
three-dot dropdown menu.

This style is no longer used anywhere in Wagtail, especially now that
the HistoryView has been reimplemented using the dropdown menu for the
actions.
2024-04-30 16:13:33 +01:00
Sage Abdullah b8dd7f484f Fix icon alignment in page listings 2024-04-30 16:13:33 +01:00
Sage Abdullah 56e69bc3ea
Use DjangoJSONEncoder instead of custom LazyStringEncoder 2024-04-30 15:17:08 +07:00
Jake Howard afbafd657d Remove duplication on performance page for frontend caching proxies (#11871) 2024-04-29 19:10:07 +01:00
Benjamin Bach b266e54ba9 Bug: Enable template tag `richtext` to convert lazy text strings (#11901)
Fixes #11900
2024-04-29 15:34:37 +01:00
Matt Westcott 763c990490 Release note for #11902 in 6.1 2024-04-29 14:18:02 +01:00
Matt Westcott 207d5dafd5 Release note for #11902 in 6.0.3 2024-04-29 14:18:02 +01:00
Sage Abdullah c3a52a6fdb Fix missing static files in the styleguide 2024-04-29 14:18:02 +01:00
Sage Abdullah 4302bed1b1
Release note for #11860 2024-04-29 14:41:49 +07:00
Sage Abdullah ae28020195
Render breadcrumbs in redirects edit view 2024-04-29 14:35:42 +07:00
rohitsrma 6f28aa9d8b
Refactor redirects edit view to extend generic EditView 2024-04-29 14:35:41 +07:00
rohitsrma 3d63d0da4f
Use pk_url_kwarg to resolve pk in generic EditView 2024-04-29 14:23:33 +07:00
elhussein almasri af86986a16 save-states-of-checkboxes-in-MultipleChooserPanel 2024-04-09 09:15:01 +00:00
67 zmienionych plików z 1021 dodań i 406 usunięć

Wyświetl plik

@ -6,10 +6,14 @@ Changelog
* Optimize and consolidate redirects report view into the index view (Jake Howard, Dan Braghis)
* Support a `HOSTNAMES` parameter on `WAGTAILFRONTENDCACHE` to define which hostnames a backend should respond to (Jake Howard, sponsored by Oxfam America)
* Refactor redirects edit view to use the generic `EditView` and breadcrumbs (Rohit Sharma)
* Fix: Make `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` setting functional again (Rohit Sharma)
* Fix: Enable `richtext` template tag to convert lazy translation values (Benjamin Bach)
* Docs: Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
* Maintenance: Use `DjangoJSONEncoder` instead of custom `LazyStringEncoder` to serialize Draftail config (Sage Abdullah)
6.1 (xx.xx.xxxx) - IN DEVELOPMENT
6.1 (01.05.2024)
~~~~~~~~~~~~~~~~
* Refine wording of page & collection privacy using password is a shared password and should not be used for secure content (Rohit Sharma, Jake Howard)
@ -49,6 +53,7 @@ Changelog
* Populate django-treebeard cache during page routing to improve performance of `get_parent` (Nigel van Keulen)
* Add a new user profile preference to configure user interface information density (Thibaud Colas)
* Add additional field types to Elasticsearch mapping (scott-8)
* Fix: CVE-2024-32882: Permission check bypass when editing a model with per-field restrictions through `wagtail.contrib.settings` or `ModelViewSet` (Ben Morse, Joshua Munn, Jake Howard, Sage Abdullah)
* Fix: Fix typo in `__str__` for MySQL search index (Jake Howard)
* Fix: Ensure that unit tests correctly check for migrations in all core Wagtail apps (Matt Westcott)
* Fix: Correctly handle `date` objects on `human_readable_date` template tag (Jhonatan Lopes)
@ -69,6 +74,8 @@ Changelog
* Fix: Improve exception handling when generating image renditions concurrently (Andy Babic)
* Fix: Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* 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)
* 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)
@ -111,11 +118,15 @@ Changelog
* Maintenance: Refactor the Django port of `urlify` to use TypeScript, officially deprecate `window.URLify` global util (LB (Ben) Johnston)
6.0.3 (xx.xx.xxxx) - IN DEVELOPMENT
6.0.3 (01.05.2024)
~~~~~~~~~~~~~~~~~~
* Fix: CVE-2024-32882: Permission check bypass when editing a model with per-field restrictions through `wagtail.contrib.settings` or `ModelViewSet` (Ben Morse, Joshua Munn, Jake Howard, Sage Abdullah)
* Fix: Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* 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: Fix generic CopyView for models with primary keys that need to be quoted (Sage Abdullah)
6.0.2 (03.04.2024)
@ -309,11 +320,12 @@ Changelog
* Maintenance: Remove support for Django 4.1 and below (Sage Abdullah)
5.2.5 (xx.xx.xxxx) - IN DEVELOPMENT
5.2.5 (01.05.2024)
~~~~~~~~~~~~~~~~~~
* Fix: Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* Fix: Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
* Fix: Provide `convert_mariadb_uuids` management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
5.2.4 (03.04.2024)

Wyświetl plik

@ -223,6 +223,10 @@ ul.listing {
.title {
word-break: break-word;
display: flex;
align-items: center;
justify-content: space-between;
gap: theme('spacing.2');
.title-wrapper,
h2 {
@ -231,6 +235,7 @@ ul.listing {
gap: theme('spacing.2');
margin: 0;
vertical-align: middle;
align-items: center;
a {
color: inherit;
@ -242,11 +247,6 @@ ul.listing {
}
}
}
.icon-folder {
margin: 3px 0.3em 0 0;
vertical-align: top;
}
}
.actions {
@ -265,36 +265,6 @@ ul.listing {
}
}
&--inline-actions td.title {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.5rem;
.title-wrapper {
margin-inline-end: 2.5em;
}
.w-status {
margin: 0;
}
}
&--inline-actions .actions {
display: inline-block;
margin-top: 0;
vertical-align: inherit;
li {
margin-bottom: 0;
}
.button {
vertical-align: inherit;
}
}
.moderate-actions form {
float: inline-start;
margin: 0 1em 1em 0;

Wyświetl plik

@ -4,6 +4,7 @@
border-radius: 2px;
text-align: center;
display: inline-block;
word-break: normal;
// stylelint-disable-next-line property-disallowed-list
text-transform: uppercase;
padding: 0 0.5em;

Wyświetl plik

@ -157,6 +157,17 @@ class SearchController {
this.request = null;
this.resultsContainer.html(resultsData);
if (this.onLoadResults) {
// save the state of the checkboxes when the user searches or navigates between pages.
const checkboxes = document.querySelectorAll(
'form[data-multiple-choice-form] input[type="checkbox"]',
);
checkboxes.forEach((checkbox) => {
const savedState = sessionStorage.getItem(checkbox.id);
if (savedState === 'true') {
checkbox.setAttribute('checked', true);
}
});
this.onLoadResults(this.resultsContainer);
}
},
@ -234,6 +245,13 @@ class ChooserModalOnloadHandlerFactory {
$('[data-multiple-choice-select]', containerElement).on('change', () => {
this.updateMultipleChoiceSubmitEnabledState(modal);
});
this.updateMultipleChoiceSubmitLocalStorage();
const form = document.querySelector('form[data-multiple-choice-form]');
form.addEventListener('submit', () => {
this.getMissingCheckboxes(form);
});
}
updateMultipleChoiceSubmitEnabledState(modal) {
@ -246,6 +264,42 @@ class ChooserModalOnloadHandlerFactory {
}
}
updateMultipleChoiceSubmitLocalStorage() {
// eslint-disable-next-line func-names
$(document).on('change', '[data-multiple-choice-select]', function () {
$(this).each(() => {
sessionStorage.setItem($(this).prop('id'), $(this).prop('checked'));
});
});
}
// get Checkbox States and create hidden inputs on submit to update the form with the missing checkboxes.
getMissingCheckboxes(form) {
for (let i = 0; i < sessionStorage.length; i += 1) {
const key = sessionStorage.key(i);
const value = sessionStorage.getItem(key);
if (
key.startsWith('chooser-modal-select') &&
value === 'true' &&
(document.getElementById(key) == null ||
(document.getElementById(key) &&
document.getElementById(key).checked !== true))
) {
const id = key.substring('chooser-modal-select-'.length);
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'id';
input.value = id;
form.appendChild(input);
}
if (key.startsWith('chooser-modal-select') && value === 'true') {
sessionStorage.setItem(key, false);
}
}
}
modalHasTabs(modal) {
return $('[data-tabs]', modal.body).length;
}

Wyświetl plik

@ -123,7 +123,7 @@ urlpatterns = [
[django-sendfile](https://github.com/johnsensible/django-sendfile) offloads the job of transferring the image data to the web
server instead of serving it directly from the Django application. This could
greatly reduce server load in situations where your site has many images being
downloaded but you're unable to use a [](caching_proxy) or a CDN.
downloaded but you're unable to use a [caching proxy](performance_frontend_caching) or a CDN.
You first need to install and configure django-sendfile and configure your
web server to use it. If you haven't done this already, please refer to the

Wyświetl plik

@ -60,16 +60,18 @@ The same can be achieved in Python using [`generate_image_url`](dynamic_image_ur
When using a queryset to render a list of images or objects with images, you can [prefetch the renditions](prefetching_image_renditions) needed with a single additional query. For long lists of items, or where multiple renditions are used for each item, this can provide a significant boost to performance.
(performance_page_urls)=
(performance_frontend_caching)=
## Frontend caching
## Frontend caching proxy
Many websites use a frontend cache such as Varnish, Squid, Cloudflare or CloudFront to gain extra performance. The downside of using a frontend cache though is that they don't respond well to updating content and will often keep an old version of a page cached after it has been updated.
Many websites use a frontend cache such as [Varnish](https://varnish-cache.org/), [Squid](http://www.squid-cache.org/), [Cloudflare](https://www.cloudflare.com/) or [CloudFront](https://aws.amazon.com/cloudfront/) to support high volumes of traffic with excellent response times. The downside of using a frontend cache though is that they don't respond well to updating content and will often keep an old version of a page cached after it has been updated.
Wagtail supports being [integrated](frontend_cache_purging) with many CDNs, so it can inform them when a page changes, so the cache can be cleared immediately and users see the changes sooner.
If you have multiple frontends configured (eg Cloudflare for one site, CloudFront for another), it's recommended to set the [`HOSTNAMES`](frontendcache_multiple_backends) key to the list of hostnames the backend can purge, to prevent unnecessary extra purge requests.
(performance_page_urls)=
## Page URLs
To fully resolve the URL of a page, Wagtail requires information from a few different sources.
@ -90,14 +92,6 @@ Wagtail is tested on PostgreSQL, SQLite, and MySQL. It may work on some third-pa
We recommend PostgreSQL for production use, however, the choice of database ultimately depends on a combination of factors, including personal preference, team expertise, and specific project requirements. The most important aspect is to ensure that your selected database can meet the performance and scalability requirements of your project.
(caching_proxy)=
## Caching proxy
To support high volumes of traffic with excellent response times, we recommend a caching proxy. Both [Varnish](https://varnish-cache.org/) and [Squid](http://www.squid-cache.org/) have been tested in production. Hosted proxies like [Cloudflare](https://www.cloudflare.com/) should also work well.
Wagtail supports automatic cache invalidation for Varnish/Squid. See [](frontend_cache_purging) for more information.
### Image attributes
For some images, it may be beneficial to lazy load images, so the rest of the page can continue to load. It can be configured site-wide [](adding_default_attributes_to_images) or per-image [](image_tag_alt). For more details you can read about the [`loading='lazy'` attribute](https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading#images_and_iframes) and the [`'decoding='async'` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-decoding) or this [web.dev article on lazy loading images](https://web.dev/lazy-loading-images/).

Wyświetl plik

@ -8,6 +8,8 @@
Wagtail provides several generic views for handling common tasks such as creating / editing model instances and chooser modals. For convenience, these views are bundled in [viewsets](viewsets_reference).
(modelviewset)=
## ModelViewSet
The {class}`~wagtail.admin.viewsets.model.ModelViewSet` class provides the views for listing, creating, editing, and deleting model instances. For example, if we have the following model:

Wyświetl plik

@ -164,3 +164,13 @@ Options:
- `--purge-only` :
This argument will purge all image renditions without regenerating them. They will be regenerated when next requested.
(convert_mariadb_uuids)=
## convert_mariadb_uuids
```sh
./manage.py convert_mariadb_uuids
```
For sites using MariaDB, this command must be run once when upgrading to Django 5.0 and MariaDB 10.7 from any earlier version of Django or MariaDB. This is necessary because Django 5.0 introduces support for MariaDB's native UUID type, breaking backwards compatibility with `CHAR`-based UUIDs used in earlier versions of Django and MariaDB. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.

Wyświetl plik

@ -1,6 +1,6 @@
# Wagtail 5.2.5 release notes - IN DEVELOPMENT
# Wagtail 5.2.5 release notes
_Unreleased_
_May 1, 2024_
```{contents}
---
@ -15,3 +15,16 @@ depth: 1
* Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
* Provide [`convert_mariadb_uuids`](convert_mariadb_uuids) management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
## Upgrade considerations
### Changes to UUID fields on MariaDB when upgrading to Django 5.0
Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with `CHAR`-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as `Data too long for column 'translation_key' at row 1` or `Data too long for column 'uuid' at row 1` when creating or editing pages. To fix this, it is necessary to run the [`convert_mariadb_uuids`](convert_mariadb_uuids) management command (available as of Wagtail 5.2.5) after upgrading:
```sh
./manage.py convert_mariadb_uuids
```
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.

Wyświetl plik

@ -219,6 +219,18 @@ As part of our [adoption of Stimulus](https://github.com/wagtail/rfcs/blob/main/
* Add better deprecation warnings to the `search.Query` & `search.QueryDailyHits` model, move final set of templates from the admin search module to the search promotions contrib module (LB (Ben) Johnston)
## Upgrade considerations - changes affecting all projects
### Changes to UUID fields on MariaDB when upgrading to Django 5.0
Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with `CHAR`-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as `Data too long for column 'translation_key' at row 1` or `Data too long for column 'uuid' at row 1` when creating or editing pages. To fix this, it is necessary to run the [`convert_mariadb_uuids`](convert_mariadb_uuids) management command (available as of Wagtail 5.2.5) after upgrading:
```sh
./manage.py convert_mariadb_uuids
```
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
## Upgrade considerations - deprecation of old functionality
### Legacy moderation system is deprecated

Wyświetl plik

@ -1,6 +1,6 @@
# Wagtail 6.0.3 release notes - IN DEVELOPMENT
# Wagtail 6.0.3 release notes
_Unreleased_
_May 1, 2024_
```{contents}
---
@ -11,7 +11,30 @@ depth: 1
## What's new
### CVE-2024-32882: Permission check bypass when editing a model with per-field restrictions through `wagtail.contrib.settings` or `ModelViewSet`
This release addresses a permission vulnerability in the Wagtail admin interface. If a model has been made available for editing through the [`wagtail.contrib.settings`](/reference/contrib/settings) module or [ModelViewSet](modelviewset), and the permission argument on FieldPanel has been used to further restrict access to one or more fields of the model, a user with edit permission over the model but not the specific field can craft an HTTP POST request that bypasses the permission check on the individual field, allowing them to update its value.
The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin, or by a user who has not been granted edit access to the model in question. The editing interfaces for pages and snippets are also unaffected.
Many thanks to Ben Morse and Joshua Munn for reporting this issue, and Jake Howard and Sage Abdullah for the fix. For further details, please see [the CVE-2024-32882 security advisory](https://github.com/wagtail/wagtail/security/advisories/GHSA-w2v8-php4-p8hc).
### Bug fixes
* Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
* Reinstate missing static files in style guide (Sage Abdullah)
* Provide [`convert_mariadb_uuids`](convert_mariadb_uuids) management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
* Fix generic CopyView for models with primary keys that need to be quoted (Sage Abdullah)
## Upgrade considerations
### Changes to UUID fields on MariaDB when upgrading to Django 5.0
Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with `CHAR`-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as `Data too long for column 'translation_key' at row 1` or `Data too long for column 'uuid' at row 1` when creating or editing pages. To fix this, it is necessary to run the [`convert_mariadb_uuids`](convert_mariadb_uuids) management command (available as of Wagtail 6.0.3) after upgrading:
```sh
./manage.py convert_mariadb_uuids
```
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.

Wyświetl plik

@ -283,6 +283,16 @@ The `use_json_field` argument to `StreamField` is no longer required, and can be
## Upgrade considerations - changes affecting all projects
### Changes to UUID fields on MariaDB when upgrading to Django 5.0
Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with `CHAR`-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as `Data too long for column 'translation_key' at row 1` or `Data too long for column 'uuid' at row 1` when creating or editing pages. To fix this, it is necessary to run the [`convert_mariadb_uuids`](convert_mariadb_uuids) management command (available as of Wagtail 6.0.3) after upgrading:
```sh
./manage.py convert_mariadb_uuids
```
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
### `SnippetViewSet` & `ModelViewSet` copy view enabled by default
The newly introduced copy view will be enabled by default for all `ModelViewSet` and `SnippetViewSet` classes.

Wyświetl plik

@ -1,6 +1,6 @@
# Wagtail 6.1 release notes - IN DEVELOPMENT
# Wagtail 6.1 release notes
_Unreleased_
_May 1, 2024_
```{contents}
---
@ -24,8 +24,12 @@ Continuing work on the Universal Listings project, this release rolls out univer
* Groups
* Users
* Workflow and task views
* Search promotions index views
* Redirects index
Universal listing components like header buttons have also been tweaked to improve usability. This feature was developed by Ben Enright and Sage Abdullah.
Universal listing components like header buttons have also been tweaked to improve usability, and the `PageListingViewSet` now includes `ChooseParentView` to allow creating pages from custom page listings.
Thank you to everyone who worked on these features: Ben Enright, Sage Abdullah, Rohit Sharma, Storm Heg, Temidayo Azeez, and Abdelrahman Hamada.
### Information-dense admin interface
@ -44,21 +48,38 @@ A new viewset class `PageListingViewSet` has been introduced, allowing developer
A new dialog is available from the help menu, providing an overview of keyboard shortcuts available in the Wagtail admin. This feature was developed by Karthik Ayangar and Rohit Sharma.
### Better guidance for password-protected content
Wagtail now includes extra guidance in its [private pages](private_pages) and [private collections (documents)](private_collections) forms, to warn users about the pitfalls of the "shared password" option.
For projects with higher security requirements, it's now possible to disable the shared password option entirely.
Thank you to Rohit Sharma, Salvo Polizzi, and Jake Howard for implementing those changes.
### Favicon images generation
For sites managing favicons via the CMS, Wagtail now supports [`.ico` favicon generation](favicon_generation), with `format-ico`:
```html+django
<link rel="icon" href="{% image favicon_image format-ico %}" />
```
This feature was developed by Jake Howard.
### CVE-2024-32882: Permission check bypass when editing a model with per-field restrictions through `wagtail.contrib.settings` or `ModelViewSet`
This release addresses a permission vulnerability in the Wagtail admin interface. If a model has been made available for editing through the [`wagtail.contrib.settings`](/reference/contrib/settings) module or [ModelViewSet](modelviewset), and the permission argument on FieldPanel has been used to further restrict access to one or more fields of the model, a user with edit permission over the model but not the specific field can craft an HTTP POST request that bypasses the permission check on the individual field, allowing them to update its value.
The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin, or by a user who has not been granted edit access to the model in question. The editing interfaces for pages and snippets are also unaffected.
Many thanks to Ben Morse and Joshua Munn for reporting this issue, and Jake Howard and Sage Abdullah for the fix. For further details, please see [the CVE-2024-32882 security advisory](https://github.com/wagtail/wagtail/security/advisories/GHSA-w2v8-php4-p8hc).
### Other features
* Refine wording of page & collection privacy using password is a shared password and should not be used for secure content (Rohit Sharma, Jake Howard)
* Add `RelatedObjectsColumn` to the table UI framework (Matt Westcott)
* Reduce memory usage when rebuilding search indexes (Jake Howard)
* Support creating images in `.ico` format (Jake Howard)
* Add the ability to disable the usage of a shared password for enhanced security for the [private pages](private_pages) and [collections (documents)](private_collections) feature (Salvo Polizzi, Jake Howard)
* Add system checks to ensure that `WAGTAIL_DATE_FORMAT`, `WAGTAIL_DATETIME_FORMAT`, `WAGTAIL_TIME_FORMAT` are [correctly configured](wagtail_date_time_formats) (Rohit Sharma, Coen van der Kamp)
* Allow custom permissions with the same prefix as built-in permissions (Sage Abdullah)
* Allow displaying permissions linked to the Admin model's content type (Sage Abdullah)
* Add support for Draftail's JavaScript to use chooserUrls provided by entity options & for the Draftail widget to encode lazy URLs/ translations (Elhussein Almasri)
* Reimplement search promotions `IndexView` using the `generic.IndexView` (Rohit Sharma, Sage Abdullah, Storm Heg)
* Reimplement redirects `IndexView` using the `generic.IndexView` (Rohit Sharma, Sage Abdullah, Temidayo Azeez)
* Add `ChooseParentView` to `PageListingViewSet` to allow creating pages from custom page listings (Abdelrahman Hamada, Sage Abdullah)
* Added `AbstractGroupApprovalTask` to simplify [customizing behavior of custom `Task` models](../extending/custom_tasks) (John-Scott Atlakson)
* Add ability to bulk toggle permissions in the user group editing view, including shift+click for multiple selections (LB (Ben) Johnston, Kalob Taulien)
* Update the minimum version of `djangorestframework` to 3.15.1 (Sage Abdullah)
@ -97,6 +118,8 @@ A new dialog is available from the help menu, providing an overview of keyboard
* Improve exception handling when generating image renditions concurrently (Andy Babic)
* Respect `WAGTAIL_ALLOW_UNICODE_SLUGS` setting when auto-generating slugs (LB (Ben) Johnston)
* Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
* Reinstate missing static files in style guide (Sage Abdullah)
* Provide [`convert_mariadb_uuids`](convert_mariadb_uuids) management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
### Documentation

Wyświetl plik

@ -16,19 +16,22 @@ depth: 1
* Optimize and consolidate redirects report view into the index view (Jake Howard, Dan Braghis)
* Support a [`HOSTNAMES` parameter on `WAGTAILFRONTENDCACHE`](frontendcache_multiple_backends) to define which hostnames a backend should respond to (Jake Howard, sponsored by Oxfam America)
* Refactor redirects edit view to use the generic `EditView` and breadcrumbs (Rohit Sharma)
### Bug fixes
* Make `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` setting functional again (Rohit Sharma)
* Enable `richtext` template tag to convert lazy translation values (Benjamin Bach)
### Documentation
* ...
* Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
### Maintenance
* ...
* Use `DjangoJSONEncoder` instead of custom `LazyStringEncoder` to serialize Draftail config (Sage Abdullah)
## Upgrade considerations - changes affecting all projects

Wyświetl plik

@ -442,6 +442,8 @@ You can encode the image into lossless AVIF or WebP format by using `format-avif
{% image page.photo width-400 format-webp-lossless %}
```
(favicon_generation)=
### Favicon generation
You can save images as a `.ico` file using `format-ico`, which is especially useful when managing a site's favicon through the Admin.

Wyświetl plik

@ -1,10 +1,10 @@
{
"version": "6.0.2",
"url": "https://docs.wagtail.org/en/stable/releases/6.0.2.html",
"minorUrl": "https://docs.wagtail.org/en/stable/releases/6.0.html",
"version": "6.1",
"url": "https://docs.wagtail.org/en/stable/releases/6.1.html",
"minorUrl": "https://docs.wagtail.org/en/stable/releases/6.1.html",
"lts": {
"version": "5.2.4",
"url": "https://docs.wagtail.org/en/stable/releases/5.2.4.html",
"version": "5.2.5",
"url": "https://docs.wagtail.org/en/stable/releases/5.2.5.html",
"minorUrl": "https://docs.wagtail.org/en/stable/releases/5.2.html"
}
}

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -50,7 +50,7 @@ msgstr ""
#: action_menu.py:196 templates/wagtailadmin/generic/confirm_unpublish.html:5
#: templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html:7
#: views/pages/bulk_actions/unpublish.py:8 wagtail_hooks.py:341
#: views/pages/bulk_actions/unpublish.py:8 wagtail_hooks.py:342
msgid "Unpublish"
msgstr ""
@ -199,7 +199,7 @@ msgstr ""
msgid "You cannot have multiple permission records for the same collection."
msgstr ""
#: forms/collections.py:378 views/generic/models.py:459
#: forms/collections.py:378 views/generic/models.py:460
msgid "Add"
msgstr ""
@ -207,21 +207,20 @@ msgstr ""
msgid "Add collections"
msgstr ""
#: forms/collections.py:379 rich_text/editors/draftail/__init__.py:24
#: templates/wagtailadmin/generic/inspect.html:31
#: forms/collections.py:379 templates/wagtailadmin/generic/inspect.html:31
#: templates/wagtailadmin/home/locked_pages.html:46
#: templates/wagtailadmin/home/recent_edits.html:35
#: templates/wagtailadmin/home/user_objects_in_workflow_moderation.html:29
#: templates/wagtailadmin/home/workflow_objects_to_moderate.html:29
#: templates/wagtailadmin/home/workflow_objects_to_moderate.html:52
#: templates/wagtailadmin/shared/workflow_history/index.html:12
#: views/generic/history.py:133 views/generic/history.py:269
#: views/generic/models.py:384 views/generic/models.py:589
#: views/generic/models.py:847 views/generic/models.py:1152
#: views/generic/models.py:1294 views/generic/models.py:1403
#: views/generic/history.py:133 views/generic/history.py:268
#: views/generic/models.py:385 views/generic/models.py:590
#: views/generic/models.py:873 views/generic/models.py:1178
#: views/generic/models.py:1320 views/generic/models.py:1429
#: views/generic/usage.py:88 views/pages/create.py:172 views/pages/edit.py:291
#: views/pages/move.py:116 views/workflows.py:236 views/workflows.py:352
#: viewsets/chooser.py:30 wagtail_hooks.py:244
#: viewsets/chooser.py:30 wagtail_hooks.py:245
msgid "Edit"
msgstr ""
@ -236,9 +235,9 @@ msgstr ""
#: templates/wagtailadmin/panels/inline_panel_child.html:11
#: templates/wagtailadmin/permissions/includes/collection_member_permissions_form.html:16
#: templates/wagtailadmin/workflows/includes/workflow_pages_form.html:8
#: views/generic/models.py:429 views/generic/models.py:699
#: views/generic/models.py:914 views/pages/bulk_actions/delete.py:8
#: wagtail_hooks.py:311
#: views/generic/models.py:430 views/generic/models.py:718
#: views/generic/models.py:940 views/pages/bulk_actions/delete.py:8
#: wagtail_hooks.py:312
msgid "Delete"
msgstr ""
@ -538,7 +537,7 @@ msgstr ""
msgid "Promote"
msgstr ""
#: panels/page_utils.py:68 wagtail_hooks.py:125
#: panels/page_utils.py:68 wagtail_hooks.py:126
msgid "Settings"
msgstr ""
@ -835,7 +834,7 @@ msgstr ""
#: templates/wagtailadmin/page_privacy/set_privacy.html:12
#: templates/wagtailadmin/workflows/edit.html:60
#: templates/wagtailadmin/workflows/edit_task.html:44
#: views/generic/models.py:702
#: views/generic/models.py:721
msgid "Save"
msgstr ""
@ -1085,7 +1084,7 @@ msgstr ""
#: templates/wagtailadmin/home/recent_edits.html:42
#: templates/wagtailadmin/shared/page_status_tag_new.html:50
#: templates/wagtailadmin/shared/side_panels/includes/status/workflow.html:18
#: views/generic/models.py:1186
#: views/generic/models.py:1212
msgid "Live"
msgstr ""
@ -1108,7 +1107,7 @@ msgid "Status"
msgstr ""
#: templates/wagtailadmin/home/recent_edits.html:14 views/generic/history.py:58
#: views/generic/history.py:226 views/reports/audit_logging.py:66
#: views/generic/history.py:225 views/reports/audit_logging.py:66
msgid "Date"
msgstr ""
@ -1674,7 +1673,7 @@ msgstr[1] ""
#: templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html:8
#: templates/wagtailadmin/pages/confirm_move.html:5
#: templates/wagtailadmin/pages/move_choose_destination.html:5
#: views/pages/bulk_actions/move.py:31 wagtail_hooks.py:289
#: views/pages/bulk_actions/move.py:31 wagtail_hooks.py:290
msgid "Move"
msgstr ""
@ -2016,8 +2015,8 @@ msgid "Copy %(title)s"
msgstr ""
#: templates/wagtailadmin/pages/copy.html:5
#: templatetags/wagtailadmin_tags.py:1328 views/generic/models.py:398
#: wagtail_hooks.py:300
#: templatetags/wagtailadmin_tags.py:1328 views/generic/models.py:399
#: wagtail_hooks.py:301
msgid "Copy"
msgstr ""
@ -2099,7 +2098,7 @@ msgstr ""
#: templates/wagtailadmin/pages/listing/_navigation_explore.html:17
#: templates/wagtailadmin/pages/listing/_navigation_explore.html:18
#: wagtail_hooks.py:280
#: wagtail_hooks.py:281
#, python-format
msgid "Add a child page to '%(title)s'"
msgstr ""
@ -2197,7 +2196,7 @@ msgid "Confirm"
msgstr ""
#: templates/wagtailadmin/pages/page_listing_header.html:12
#: wagtail_hooks.py:278
#: wagtail_hooks.py:279
msgid "Add child page"
msgstr ""
@ -2322,7 +2321,7 @@ msgid "App"
msgstr ""
#: templates/wagtailadmin/reports/listing/_list_page_types_usage.html:19
#: wagtail_hooks.py:102 wagtail_hooks.py:143
#: wagtail_hooks.py:103 wagtail_hooks.py:144
msgid "Pages"
msgstr ""
@ -2368,7 +2367,7 @@ msgstr ""
#: templates/wagtailadmin/reports/site_history.html:10
#: templates/wagtailadmin/workflows/task_chooser/includes/results.html:19
#: views/account.py:152 views/collections.py:27 views/generic/models.py:254
#: views/account.py:152 views/collections.py:27 views/generic/models.py:255
#: views/generic/usage.py:103 views/reports/audit_logging.py:68
#: views/reports/audit_logging.py:114 views/workflows.py:125
#: views/workflows.py:520
@ -2376,7 +2375,7 @@ msgid "Name"
msgstr ""
#: templates/wagtailadmin/reports/site_history.html:16
#: views/generic/history.py:48 views/generic/history.py:214
#: views/generic/history.py:48 views/generic/history.py:213
#: views/reports/audit_logging.py:57
msgid "Action"
msgstr ""
@ -2502,8 +2501,8 @@ msgstr ""
#: templates/wagtailadmin/shared/headers/_history_icon_link.html:5
#: templates/wagtailadmin/shared/headers/_history_icon_link.html:7
#: views/generic/history.py:194 views/generic/history.py:259
#: views/generic/models.py:1153 wagtail_hooks.py:352
#: views/generic/history.py:194 views/generic/history.py:258
#: views/generic/models.py:1179 wagtail_hooks.py:353
msgid "History"
msgstr ""
@ -2949,7 +2948,7 @@ msgstr ""
#: templates/wagtailadmin/workflows/create.html:36
#: templates/wagtailadmin/workflows/create_task.html:32
#: templates/wagtailadmin/workflows/task_chooser/includes/create_form.html:30
#: views/generic/chooser.py:302 views/generic/models.py:508
#: views/generic/chooser.py:302 views/generic/models.py:509
#: viewsets/chooser.py:82
msgid "Create"
msgstr ""
@ -3050,7 +3049,7 @@ msgid "Choose a task"
msgstr ""
#: templates/wagtailadmin/workflows/task_chooser/chooser.html:8
#: views/generic/models.py:502 views/pages/create.py:67
#: views/generic/models.py:503 views/pages/create.py:67
msgid "New"
msgstr ""
@ -3241,11 +3240,11 @@ msgstr ""
msgid "Text formatting"
msgstr ""
#: templatetags/wagtailadmin_tags.py:1351 wagtail_hooks.py:693
#: templatetags/wagtailadmin_tags.py:1351 wagtail_hooks.py:694
msgid "Bold"
msgstr ""
#: templatetags/wagtailadmin_tags.py:1352 wagtail_hooks.py:715
#: templatetags/wagtailadmin_tags.py:1352 wagtail_hooks.py:716
msgid "Italic"
msgstr ""
@ -3261,11 +3260,11 @@ msgstr ""
msgid "Strike-through"
msgstr ""
#: templatetags/wagtailadmin_tags.py:1356 wagtail_hooks.py:785
#: templatetags/wagtailadmin_tags.py:1356 wagtail_hooks.py:786
msgid "Superscript"
msgstr ""
#: templatetags/wagtailadmin_tags.py:1357 wagtail_hooks.py:806
#: templatetags/wagtailadmin_tags.py:1357 wagtail_hooks.py:807
msgid "Subscript"
msgstr ""
@ -3391,7 +3390,7 @@ msgstr ""
msgid "You have been successfully logged out."
msgstr ""
#: views/collections.py:21 wagtail_hooks.py:174
#: views/collections.py:21 wagtail_hooks.py:175
msgid "Collections"
msgstr ""
@ -3455,7 +3454,7 @@ msgstr ""
msgid "Cancel scheduled publish"
msgstr ""
#: views/generic/history.py:356
#: views/generic/history.py:355
msgid "Workflow progress"
msgstr ""
@ -3469,12 +3468,12 @@ msgstr ""
msgid "The %(model_name)s could not be saved as it is locked"
msgstr ""
#: views/generic/mixins.py:418 views/generic/models.py:700
#: views/generic/mixins.py:418 views/generic/models.py:719
#, python-format
msgid "%(model_name)s '%(object)s' updated."
msgstr ""
#: views/generic/mixins.py:420 views/generic/models.py:504
#: views/generic/mixins.py:420 views/generic/models.py:505
#, python-format
msgid "%(model_name)s '%(object)s' created."
msgstr ""
@ -3553,97 +3552,97 @@ msgid ""
"for publishing."
msgstr ""
#: views/generic/models.py:284
#: views/generic/models.py:285
#, python-format
msgid "%(related_model_name)s %(field_label)s"
msgstr ""
#: views/generic/models.py:388 wagtail_hooks.py:246
#: views/generic/models.py:389 wagtail_hooks.py:247
#, python-format
msgid "Edit '%(title)s'"
msgstr ""
#: views/generic/models.py:402
#: views/generic/models.py:403
#, python-format
msgid "Copy '%(title)s'"
msgstr ""
#: views/generic/models.py:411 views/generic/models.py:1056
#: views/generic/models.py:412 views/generic/models.py:1082
msgid "Inspect"
msgstr ""
#: views/generic/models.py:415
#: views/generic/models.py:416
#, python-format
msgid "Inspect '%(title)s'"
msgstr ""
#: views/generic/models.py:433
#: views/generic/models.py:434
#, python-format
msgid "Delete '%(title)s'"
msgstr ""
#: views/generic/models.py:447 wagtail_hooks.py:236
#: views/generic/models.py:448 wagtail_hooks.py:237
#, python-format
msgid "More options for '%(title)s'"
msgstr ""
#: views/generic/models.py:457
#: views/generic/models.py:458
#, python-format
msgid "Add %(model_name)s"
msgstr ""
#: views/generic/models.py:506
#: views/generic/models.py:507
#, python-format
msgid "The %(model_name)s could not be created due to errors."
msgstr ""
#: views/generic/models.py:543 views/workflows.py:644
#: views/generic/models.py:544 views/workflows.py:644
#, python-format
msgid "New: %(model_name)s"
msgstr ""
#: views/generic/models.py:695
#: views/generic/models.py:714
msgid "Editing"
msgstr ""
#: views/generic/models.py:701
#: views/generic/models.py:720
#, python-format
msgid "The %(model_name)s could not be saved due to errors."
msgstr ""
#: views/generic/models.py:915
#: views/generic/models.py:941
#, python-format
msgid "%(model_name)s '%(object)s' deleted."
msgstr ""
#: views/generic/models.py:974
#: views/generic/models.py:1000
#, python-format
msgid "Are you sure you want to delete this %(model_name)s?"
msgstr ""
#: views/generic/models.py:1019
#: views/generic/models.py:1045
msgid "Inspecting"
msgstr ""
#: views/generic/models.py:1191
#: views/generic/models.py:1217
msgid "Earliest"
msgstr ""
#: views/generic/models.py:1194
#: views/generic/models.py:1220
msgid "Latest"
msgstr ""
#: views/generic/models.py:1257
#: views/generic/models.py:1283
#, python-format
msgid "'%(object)s' unpublished."
msgstr ""
#: views/generic/models.py:1364
#: views/generic/models.py:1390
#, python-format
msgid "Version %(revision_id)s of \"%(object)s\" unscheduled."
msgstr ""
#: views/generic/models.py:1420
#: views/generic/models.py:1446
#, python-format
msgid "revision %(revision_id)s of \"%(object)s\""
msgstr ""
@ -3819,11 +3818,11 @@ msgstr ""
msgid "Page '%(page_title)s' copied."
msgstr ""
#: views/pages/create.py:178 views/pages/edit.py:297 wagtail_hooks.py:255
#: views/pages/create.py:178 views/pages/edit.py:297 wagtail_hooks.py:256
msgid "View draft"
msgstr ""
#: views/pages/create.py:183 views/pages/edit.py:302 wagtail_hooks.py:267
#: views/pages/create.py:183 views/pages/edit.py:302 wagtail_hooks.py:268
msgid "View live"
msgstr ""
@ -4030,7 +4029,7 @@ msgstr ""
msgid "Last published before"
msgstr ""
#: views/reports/aging_pages.py:33 wagtail_hooks.py:946
#: views/reports/aging_pages.py:33 wagtail_hooks.py:947
msgid "Aging pages"
msgstr ""
@ -4042,7 +4041,7 @@ msgstr ""
msgid "Hide commenting actions"
msgstr ""
#: views/reports/audit_logging.py:108 wagtail_hooks.py:935
#: views/reports/audit_logging.py:108 wagtail_hooks.py:936
msgid "Site history"
msgstr ""
@ -4058,11 +4057,11 @@ msgstr ""
msgid "Date/Time"
msgstr ""
#: views/reports/locked_pages.py:38 wagtail_hooks.py:902
#: views/reports/locked_pages.py:38 wagtail_hooks.py:903
msgid "Locked pages"
msgstr ""
#: views/reports/page_types_usage.py:100 wagtail_hooks.py:957
#: views/reports/page_types_usage.py:100 wagtail_hooks.py:958
msgid "Page types usage"
msgstr ""
@ -4075,7 +4074,7 @@ msgid "Awaiting my review"
msgstr ""
#: views/reports/workflows.py:139 views/workflows.py:119 views/workflows.py:588
#: wagtail_hooks.py:205 wagtail_hooks.py:913
#: wagtail_hooks.py:206 wagtail_hooks.py:914
msgid "Workflows"
msgstr ""
@ -4091,8 +4090,8 @@ msgstr ""
msgid "Page/Snippet Title"
msgstr ""
#: views/reports/workflows.py:211 views/workflows.py:514 wagtail_hooks.py:216
#: wagtail_hooks.py:924
#: views/reports/workflows.py:211 views/workflows.py:514 wagtail_hooks.py:217
#: wagtail_hooks.py:925
msgid "Workflow tasks"
msgstr ""
@ -4222,98 +4221,98 @@ msgstr ""
msgid "Choose another"
msgstr ""
#: wagtail_hooks.py:257
#: wagtail_hooks.py:258
#, python-format
msgid "Preview draft version of '%(title)s'"
msgstr ""
#: wagtail_hooks.py:269
#: wagtail_hooks.py:270
#, python-format
msgid "View live version of '%(title)s'"
msgstr ""
#: wagtail_hooks.py:291
#: wagtail_hooks.py:292
#, python-format
msgid "Move page '%(title)s'"
msgstr ""
#: wagtail_hooks.py:302
#: wagtail_hooks.py:303
#, python-format
msgid "Copy page '%(title)s'"
msgstr ""
#: wagtail_hooks.py:313
#: wagtail_hooks.py:314
#, python-format
msgid "Delete page '%(title)s'"
msgstr ""
#: wagtail_hooks.py:343
#: wagtail_hooks.py:344
#, python-format
msgid "Unpublish page '%(title)s'"
msgstr ""
#: wagtail_hooks.py:354
#: wagtail_hooks.py:355
#, python-format
msgid "View page history for '%(title)s'"
msgstr ""
#: wagtail_hooks.py:363
#: wagtail_hooks.py:364
msgid "Sort menu order"
msgstr ""
#: wagtail_hooks.py:365
#: wagtail_hooks.py:366
#, python-format
msgid "Change ordering of child pages of '%(title)s'"
msgstr ""
#: wagtail_hooks.py:497 wagtail_hooks.py:518 wagtail_hooks.py:539
#: wagtail_hooks.py:560 wagtail_hooks.py:581 wagtail_hooks.py:602
#: wagtail_hooks.py:498 wagtail_hooks.py:519 wagtail_hooks.py:540
#: wagtail_hooks.py:561 wagtail_hooks.py:582 wagtail_hooks.py:603
#, python-format
msgid "Heading %(level)d"
msgstr ""
#: wagtail_hooks.py:623
#: wagtail_hooks.py:624
msgid "Bulleted list"
msgstr ""
#: wagtail_hooks.py:647
#: wagtail_hooks.py:648
msgid "Numbered list"
msgstr ""
#: wagtail_hooks.py:671
#: wagtail_hooks.py:672
msgid "Blockquote"
msgstr ""
#: wagtail_hooks.py:738
#: wagtail_hooks.py:739
msgid "Link"
msgstr ""
#: wagtail_hooks.py:827
#: wagtail_hooks.py:828
msgid "Strikethrough"
msgstr ""
#: wagtail_hooks.py:848
#: wagtail_hooks.py:849
msgid "Code"
msgstr ""
#: wagtail_hooks.py:968
#: wagtail_hooks.py:969
msgid "Reports"
msgstr ""
#: wagtail_hooks.py:980
#: wagtail_hooks.py:981
#, python-format
msgid "What's new in Wagtail %(version)s"
msgstr ""
#: wagtail_hooks.py:992
#: wagtail_hooks.py:993
msgid "Editor Guide"
msgstr ""
#: wagtail_hooks.py:1009
#: wagtail_hooks.py:1010
msgid "Shortcuts"
msgstr ""
#: wagtail_hooks.py:1026
#: wagtail_hooks.py:1027
msgid "Help"
msgstr ""

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -98,6 +98,9 @@ msgstr "Raccolta"
msgid "Tag"
msgstr "Tag"
msgid "Filter by up to ten most popular tags."
msgstr "Filtra fino a dieci tag più popolari."
msgid "Preferred language"
msgstr "Lingua preferita"
@ -263,6 +266,20 @@ msgstr "Seleziona un nuovo genitore per questa pagina."
msgid "Parent page"
msgstr "Pagina padre"
msgid "The new page will be a child of this given parent page."
msgstr "Questa nuova pagina sarà un figlio della pagina padre in questione."
#, python-format
msgid "You do not have permission to create a page under \"%(page_title)s\"."
msgstr "Non hai i permessi per creare una pagina sotto \"%(page_title)s\""
#, python-format
msgid ""
"You cannot create a page of type \"%(page_type)s\" under \"%(page_title)s\"."
msgstr ""
"Non puoi creare una pagina del tipo \"%(page_type)s\" sotto "
"\"%(page_title)s\"."
msgid "Search…"
msgstr "Cerca..."
@ -659,13 +676,12 @@ msgid ""
"No collections have been created. Why not <a "
"href=\"%(add_collection_url)s\">add one</a>?"
msgstr ""
"Nessuna raccolta presente. Perché non ne <a "
"href=\"%(add_collection_url)s\">aggiungi una</a>?"
"Non ci sono raccolte presenti. Perché non ne <a "
"href=\"%(add_collection_url)s\">crei una</a>?"
#, python-format
msgid "Sorry, there are no matches for \"<em>%(search_query)s</em>\""
msgstr ""
"Spiacente, non ci sono corrispondenze per \"<em>%(search_query)s</em>\""
msgstr "Non ci sono corrispondenze per \"<em>%(search_query)s</em>\""
msgid "There are no results."
msgstr "Non ci sono risultati."
@ -1479,6 +1495,25 @@ msgstr[2] ""
"L'eliminazione di questa pagina eliminerà anche 1 traduzione e le sue "
"%(translation_descendant_count)s pagine figlie tradotte combinate."
#, python-format
msgid ""
"Deleting this page will also delete %(translation_count)s translations and "
"their combined %(translation_descendant_count)s translated child page."
msgid_plural ""
"Deleting this page will also delete %(translation_count)s translations and "
"their combined %(translation_descendant_count)s translated child pages."
msgstr[0] ""
"L'eliminazione di questa pagina eliminerà anche %(translation_count)s "
"traduzioni e la loro pagina figlia tradotta %(translation_descendant_count)s."
msgstr[1] ""
"L'eliminazione di questa pagina eliminerà anche %(translation_count)s "
"traduzioni e le relative %(translation_descendant_count)s pagine figlie "
"tradotte."
msgstr[2] ""
"L'eliminazione di questa pagina eliminerà anche %(translation_count)s "
"traduzioni e le relative %(translation_descendant_count)s pagine figlie "
"tradotte."
#, python-format
msgid "This action will delete total <b>%(total_pages)s</b> pages."
msgstr "Questa azione eliminerà un totale di <b>%(total_pages)s</b> pagine."
@ -1897,6 +1932,18 @@ msgstr "Torna indietro"
msgid "History"
msgstr "Storico"
msgid "Keyboard shortcuts"
msgstr "Scorciatoie da tastiera"
msgid "All keyboard shortcuts"
msgstr "Tuttle le scorciatoie da dastiera"
msgid "Section"
msgstr "Sezione"
msgid "Keyboard shortcut"
msgstr "Scorciatoia da tastiera"
msgid "Current page status:"
msgstr "Stato attuale della pagina:"
@ -2426,18 +2473,48 @@ msgstr "Inviato a %(task_name)s %(started_at)s"
msgid "%(status_display)s %(task_name)s %(started_at)s"
msgstr "%(status_display)s %(task_name)s %(started_at)s"
msgid "Common actions"
msgstr "Azioni comuni"
msgid "Cut"
msgstr "Taglia"
msgid "Paste"
msgstr "Incolla"
msgid "Paste and match style"
msgstr "Incolla e mantieni lo stile"
msgid "Paste without formatting"
msgstr "Incolla senza formattazione"
msgid "Undo"
msgstr "Annulla"
msgid "Redo"
msgstr "Ripristina"
msgid "Save changes"
msgstr "Salva modifiche"
msgid "Text content"
msgstr "Contenuto testo"
msgid "Insert or edit a link"
msgstr "Inserisci o modifica un link"
msgid "Text formatting"
msgstr "Formattazione testo"
msgid "Bold"
msgstr "Grassetto"
msgid "Italic"
msgstr "Corsivo"
msgid "Underline"
msgstr "Sottolineatura"
msgid "Superscript"
msgstr "Apice"
@ -2610,6 +2687,10 @@ msgstr "Cancella programma pubblicazione"
msgid "Workflow progress"
msgstr "Andamento flusso di lavoro"
#, python-format
msgid "%(model_name)s '%(title)s' is now unlocked."
msgstr "%(model_name)s '%(title)s' è sbloccata ora."
#, python-format
msgid "%(model_name)s '%(object)s' updated."
msgstr "%(model_name)s '%(object)s' aggiornato."
@ -2622,6 +2703,10 @@ msgstr "%(model_name)s '%(object)s' creato."
msgid "Edit '%(title)s'"
msgstr "Modifica '%(title)s'"
#, python-format
msgid "Copy '%(title)s'"
msgstr "Copia '%(title)s'"
msgid "Inspect"
msgstr "Controlla"
@ -2902,6 +2987,9 @@ msgstr "La pagina non può esser salvata a causa di errori di validazione"
msgid "Owner"
msgstr "Proprietario"
msgid "Edited by"
msgstr "Modificata da"
msgid "Site"
msgstr "Sito"
@ -2911,6 +2999,9 @@ msgstr "Qualsiasi"
msgid "Yes"
msgstr "Sì"
msgid "Page type"
msgstr "Tipologia pagina"
#, python-format
msgid "Page '%(page_title)s' is now unlocked."
msgstr "Pagina '%(page_title)s' sbloccata."
@ -2984,6 +3075,9 @@ msgstr "Data/Ora"
msgid "Locked pages"
msgstr "Pagine bloccate"
msgid "Page types usage"
msgstr "Utilizzo tipologie pagine"
msgid "Show"
msgstr "Mostra"
@ -3008,6 +3102,9 @@ msgstr "Attività nei flussi di lavoro"
msgid "Requested By"
msgstr "Richiesto da"
msgid "Show disabled"
msgstr "Mostra disabilitate"
msgid "Add a workflow"
msgstr "Aggiungi un flusso di lavoro"
@ -3041,6 +3138,26 @@ msgstr "Disabilita flusso di lavoro"
msgid "Workflow '%(object)s' disabled."
msgstr "Flusso di lavoro '%(object)s' disabilitato."
#, python-format
msgid ""
"This workflow is in progress on %(states_in_progress)d page/snippet. "
"Disabling this workflow will cancel moderation on this page/snippet."
msgid_plural ""
"This workflow is in progress on %(states_in_progress)d pages/snippets. "
"Disabling this workflow will cancel moderation on these pages/snippets."
msgstr[0] ""
"Questo flusso di lavoro è in corso sulla pagina/snippet "
"%(states_in_progress)d. Se disabiliti questo flusso di lavoro verrà rimossa "
"la moderazione da questa pagina/snippet."
msgstr[1] ""
"Questo flusso di lavoro è in corso sulle pagine/snippet "
"%(states_in_progress)d. Se disabiliti questo flusso di lavoro verrà rimossa "
"la moderazione da queste pagine/snippet."
msgstr[2] ""
"Questo flusso di lavoro è in corso sulle pagine/snippet "
"%(states_in_progress)d. Se disabiliti questo flusso di lavoro verrà rimossa "
"la moderazione da queste pagine/snippet."
#, python-format
msgid "Workflow '%(workflow_name)s' enabled."
msgstr "Flusso di lavoro '%(workflow_name)s' abilitato."
@ -3148,6 +3265,12 @@ msgstr "Cosa c'è di nuovo in Wagtail %(version)s"
msgid "Editor Guide"
msgstr "Guida editor"
msgid "Shortcuts"
msgstr "Scorciatoie"
msgid "Help"
msgstr "Aiuto"
msgid "Choose an item"
msgstr "Scegli un elemento"

Wyświetl plik

@ -1,10 +1,9 @@
import json
import warnings
from django.core.serializers.json import DjangoJSONEncoder
from django.forms import Media, widgets
from django.urls import reverse_lazy
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy
from wagtail.admin.rich_text.converters.contentstate import ContentstateConverter
from wagtail.admin.staticfiles import versioned_static
@ -13,23 +12,6 @@ from wagtail.telepath import register
from wagtail.widget_adapters import WidgetAdapter
class LazyStringEncoder(json.JSONEncoder):
"""
Add support for lazy strings to the JSON encoder so that URLs and
translations can be resolved when rendering the widget only.
"""
# The string "Edit" here is arbitrary, chosen because it exists elsewhere in the
# translations dictionary and is likely to remain in the future.
lazy_string_types = [type(reverse_lazy("Edit")), type(gettext_lazy("Edit"))]
def default(self, obj):
if type(obj) in self.lazy_string_types:
return str(obj)
return json.JSONEncoder.default(self, obj)
class DraftailRichTextArea(widgets.HiddenInput):
template_name = "wagtailadmin/widgets/draftail_rich_text_area.html"
is_hidden = False
@ -90,7 +72,7 @@ class DraftailRichTextArea(widgets.HiddenInput):
context = super().get_context(name, value, attrs)
context["widget"]["attrs"]["data-w-init-detail-value"] = json.dumps(
self.options,
cls=LazyStringEncoder,
cls=DjangoJSONEncoder,
)
return context

Wyświetl plik

@ -5,7 +5,7 @@
<div class="title-wrapper">
{% if page.is_site_root %}
{% if perms.wagtailcore.add_site or perms.wagtailcore.change_site or perms.wagtailcore.delete_site %}
<a href="{% url 'wagtailsites:index' %}" title="{% trans 'Sites menu' %}">{% icon name="site" classname="initial" %}</a>
<a href="{% url 'wagtailsites:index' %}" title="{% trans 'Sites menu' %}" class="w-flex w-items-center">{% icon name="site" classname="initial" %}</a>
{% endif %}
{% endif %}
@ -17,7 +17,7 @@
without also reading out the buttons and indicators.
{% endcomment %}
{% fragment as page_title %}
<span id="page_{{ page.pk|unlocalize|admin_urlquote }}_title">
<span id="page_{{ page.pk|unlocalize|admin_urlquote }}_title" class="w-flex w-items-center w-gap-2">
{% if not page.is_site_root and not page.is_leaf %}{% icon name="folder" classname="initial" %}{% endif %}
{{ page.get_admin_display_title }}
</span>

Wyświetl plik

@ -133,13 +133,15 @@ class TestPageExplorer(WagtailTestUtils, TestCase):
def test_explore_root_shows_icon(self):
response = self.client.get(reverse("wagtailadmin_explore_root"))
self.assertEqual(response.status_code, 200)
soup = self.get_soup(response.content)
# Administrator (or user with add_site permission) should see the
# sites link with its icon
self.assertContains(
response,
'<a href="/admin/sites/" title="Sites menu"><svg',
)
url = reverse("wagtailsites:index")
link = soup.select_one(f'td a[href="{url}"]')
self.assertIsNotNone(link)
icon = link.select_one("svg use[href='#icon-site']")
self.assertIsNotNone(icon)
def test_ordering(self):
response = self.client.get(

Wyświetl plik

@ -1571,6 +1571,35 @@ class TestEditHandler(WagtailTestUtils, TestCase):
self.assertIsNotNone(rendered_heading)
self.assertEqual(rendered_heading.text.strip(), expected_heading)
def test_field_permissions(self):
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
),
Permission.objects.get(
content_type__app_label=self.object._meta.app_label,
codename=get_permission_codename("change", self.object._meta),
),
)
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(list(response.context["form"].fields), ["name"])
self.user.user_permissions.add(
Permission.objects.get(
codename="can_set_release_date",
)
)
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(
list(response.context["form"].fields), ["name", "release_date"]
)
class TestDefaultMessages(WagtailTestUtils, TestCase):
def setUp(self):

Wyświetl plik

@ -518,7 +518,3 @@ class Table(Component):
@cached_property
def attrs(self):
return self.table.get_row_attrs(self.instance)
class InlineActionsTable(Table):
classname = "listing listing--inline-actions"

Wyświetl plik

@ -16,7 +16,7 @@ from wagtail.admin.filters import (
MultipleUserFilter,
WagtailFilterSet,
)
from wagtail.admin.ui.tables import Column, DateColumn, InlineActionsTable, UserColumn
from wagtail.admin.ui.tables import Column, DateColumn, UserColumn
from wagtail.admin.utils import get_latest_str
from wagtail.admin.views.generic.base import (
BaseListingView,
@ -197,7 +197,6 @@ class HistoryView(PermissionCheckedMixin, BaseObjectMixin, BaseListingView):
is_searchable = False
paginate_by = 20
filterset_class = HistoryFilterSet
table_class = InlineActionsTable
history_url_name = None
history_results_url_name = None
edit_url_name = None

Wyświetl plik

@ -28,6 +28,7 @@ from django.views.generic.edit import (
from wagtail.actions.unpublish import UnpublishAction
from wagtail.admin import messages
from wagtail.admin.filters import WagtailFilterSet
from wagtail.admin.forms.models import WagtailAdminModelForm
from wagtail.admin.forms.search import SearchForm
from wagtail.admin.panels import get_edit_handler
from wagtail.admin.ui.components import Component, MediaContainer
@ -628,6 +629,24 @@ class CreateView(
for locale in Locale.objects.all().exclude(id=self.locale.id)
]
def get_initial_form_instance(self):
if self.locale:
instance = self.model()
instance.locale = self.locale
return instance
def get_form_kwargs(self):
if instance := self.get_initial_form_instance():
# super().get_form_kwargs() will use self.object as the instance kwarg
self.object = instance
kwargs = super().get_form_kwargs()
form_class = self.get_form_class()
# Add for_user support for PermissionedForm
if issubclass(form_class, WagtailAdminModelForm):
kwargs["for_user"] = self.request.user
return kwargs
def save_instance(self):
"""
Called after the form is successfully validated - saves the object to the db
@ -716,9 +735,9 @@ class EditView(
return self.actions
def get_object(self, queryset=None):
if "pk" not in self.kwargs:
self.kwargs["pk"] = self.args[0]
self.kwargs["pk"] = unquote(str(self.kwargs["pk"]))
if self.pk_url_kwarg not in self.kwargs:
self.kwargs[self.pk_url_kwarg] = self.args[0]
self.kwargs[self.pk_url_kwarg] = unquote(str(self.kwargs[self.pk_url_kwarg]))
return super().get_object(queryset)
def get_page_subtitle(self):
@ -802,6 +821,13 @@ class EditView(
for translation in self.object.get_translations().select_related("locale")
]
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
form_class = self.get_form_class()
if issubclass(form_class, WagtailAdminModelForm):
kwargs["for_user"] = self.request.user
return kwargs
def save_instance(self):
"""
Called after the form is successfully validated - saves the object to the db.

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -22,20 +22,19 @@ msgstr ""
msgid "Wagtail redirects"
msgstr ""
#: filters.py:12 templates/wagtailredirects/list.html:20 views.py:102
#: views.py:466
#: filters.py:26 views.py:102 views.py:119
msgid "Type"
msgstr ""
#: filters.py:15
#: filters.py:29
msgid "Permanent"
msgstr ""
#: filters.py:16
#: filters.py:30
msgid "Temporary"
msgstr ""
#: filters.py:18
#: filters.py:32
msgid "All"
msgstr ""
@ -68,59 +67,59 @@ msgstr ""
msgid "To field"
msgstr ""
#: models.py:12
#: models.py:13
msgid "redirect from"
msgstr ""
#: models.py:16
#: models.py:17
msgid "site"
msgstr ""
#: models.py:24 models.py:84
#: models.py:25 models.py:85
msgid "permanent"
msgstr ""
#: models.py:27
#: models.py:28
msgid ""
"Recommended. Permanent redirects ensure search engines forget the old page "
"(the 'Redirect from') and index the new page instead."
msgstr ""
#: models.py:33
#: models.py:34
msgid "redirect to a page"
msgstr ""
#: models.py:39
#: models.py:40
msgid "target page route"
msgstr ""
#: models.py:41
#: models.py:42
msgid ""
"Optionally specify a route on the target page to redirect to. Leave blank to "
"redirect to the default page route."
msgstr ""
#: models.py:48
#: models.py:49
msgid "redirect to any URL"
msgstr ""
#: models.py:51
#: models.py:52
msgid "automatically created"
msgstr ""
#: models.py:56
#: models.py:57
msgid "created at"
msgstr ""
#: models.py:86
#: models.py:87
msgid "temporary"
msgstr ""
#: models.py:203
#: models.py:204
msgid "redirect"
msgstr ""
#: models.py:204
#: models.py:205
msgid "redirects"
msgstr ""
@ -130,7 +129,6 @@ msgid "Add redirect"
msgstr ""
#: templates/wagtailredirects/add.html:19
#: templates/wagtailredirects/edit.html:19
msgid "Save"
msgstr ""
@ -141,7 +139,7 @@ msgstr ""
#: templates/wagtailredirects/choose_import_file.html:6
#: templates/wagtailredirects/confirm_import.html:6
#: templates/wagtailredirects/import_summary.html:5 views.py:116
#: templates/wagtailredirects/import_summary.html:5 views.py:130
msgid "Import redirects"
msgstr ""
@ -191,19 +189,6 @@ msgstr ""
msgid "Preview"
msgstr ""
#: templates/wagtailredirects/edit.html:3
#, python-format
msgid "Editing %(title)s"
msgstr ""
#: templates/wagtailredirects/edit.html:5
msgid "Editing"
msgstr ""
#: templates/wagtailredirects/edit.html:21
msgid "Delete redirect"
msgstr ""
#: templates/wagtailredirects/import_summary.html:3
#: templates/wagtailredirects/import_summary.html:6
msgid "Summary"
@ -215,14 +200,11 @@ msgid ""
"Found %(total)s redirects, created %(successes)s and found %(errors)s errors."
msgstr ""
#: templates/wagtailredirects/import_summary.html:17
#: templates/wagtailredirects/list.html:12
#: templates/wagtailredirects/list.html:15 views.py:84 views.py:463
#: templates/wagtailredirects/import_summary.html:17 views.py:84 views.py:116
msgid "From"
msgstr ""
#: templates/wagtailredirects/import_summary.html:18
#: templates/wagtailredirects/list.html:19 views.py:96 views.py:465
#: templates/wagtailredirects/import_summary.html:18 views.py:96 views.py:118
msgid "To"
msgstr ""
@ -246,76 +228,59 @@ msgid ""
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
msgstr ""
#: templates/wagtailredirects/list.html:18 views.py:90 views.py:464
#: views.py:90 views.py:117
msgid "Site"
msgstr ""
#: templates/wagtailredirects/list.html:27
msgid "Edit this redirect"
#: views.py:148
msgid "The redirect could not be saved due to errors."
msgstr ""
#: templates/wagtailredirects/reports/redirects_report.html:8
#: templates/wagtailredirects/reports/redirects_report.html:13
msgid "No redirects found."
msgstr ""
#: views.py:122
msgid "Export redirects"
msgstr ""
#: views.py:147
#: views.py:153
#, python-format
msgid "Redirect '%(redirect_title)s' updated."
msgstr ""
#: views.py:152 views.py:220
msgid "Edit"
msgstr ""
#: views.py:158
msgid "The redirect could not be saved due to errors."
msgstr ""
#: views.py:190
#: views.py:173
#, python-format
msgid "Redirect '%(redirect_title)s' deleted."
msgstr ""
#: views.py:215
#: views.py:198
#, python-format
msgid "Redirect '%(redirect_title)s' added."
msgstr ""
#: views.py:227
#: views.py:203
msgid "Edit"
msgstr ""
#: views.py:210
msgid "The redirect could not be created due to errors."
msgstr ""
#: views.py:266
#: views.py:249
msgid "Search redirects"
msgstr ""
#: views.py:280
#: views.py:263
#, python-format
msgid "File format of type \"%(extension)s\" is not supported"
msgstr ""
#: views.py:297
#: views.py:280
#, python-format
msgid "Imported file has a wrong encoding: %(error_message)s"
msgstr ""
#: views.py:304
#: views.py:287
#, python-format
msgid "%(error)s encountered while trying to read file: %(filename)s"
msgstr ""
#: views.py:395
#: views.py:378
#, python-format
msgid "Imported %(total)d redirect"
msgid_plural "Imported %(total)d redirects"
msgstr[0] ""
msgstr[1] ""
#: views.py:451
msgid "Export Redirects"
msgstr ""

Wyświetl plik

@ -1,38 +1 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n wagtailadmin_tags %}
{% block titletag %}{% blocktrans trimmed with title=redirect.title %}Editing {{ title }}{% endblocktrans %}{% endblock %}
{% block content %}
{% trans "Editing" as editing_str %}
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=redirect.title icon="redirect" %}
{% include "wagtailadmin/shared/non_field_errors.html" %}
<form action="{% url 'wagtailredirects:edit' redirect.id %}" method="POST" class="nice-padding" novalidate>
{% csrf_token %}
<ul class="fields">
{% for field in form.visible_fields %}
<li>{% formattedfield field %}</li>
{% endfor %}
<li>
<input type="submit" value="{% trans 'Save' %}" class="button" />
{% if user_can_delete %}
<a href="{% url 'wagtailredirects:delete' redirect.id %}" class="button no">{% trans "Delete redirect" %}</a>
{% endif %}
</li>
</ul>
</form>
{% endblock %}
{% block extra_js %}
{{ block.super }}
{% include "wagtailadmin/pages/_editor_js.html" %}
{{ form.media.js }}
{% endblock %}
{% block extra_css %}
{{ block.super }}
{{ form.media.css }}
{% endblock %}
{% extends "wagtailadmin/generic/edit.html" %}

Wyświetl plik

@ -1,6 +1,7 @@
from io import BytesIO
from django.conf import settings
from django.contrib.auth.models import Permission
from django.test import TestCase, override_settings
from django.urls import reverse
from openpyxl.reader.excel import load_workbook
@ -948,7 +949,7 @@ class TestRedirectsAddView(WagtailTestUtils, TestCase):
self.assertIsNone(redirects.first().site)
class TestRedirectsEditView(WagtailTestUtils, TestCase):
class TestRedirectsEditView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
def setUp(self):
# Create a redirect to edit
self.redirect = models.Redirect(
@ -975,6 +976,13 @@ class TestRedirectsEditView(WagtailTestUtils, TestCase):
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailredirects/edit.html")
self.assertBreadcrumbsItemsRendered(
[
{"url": reverse("wagtailredirects:index"), "label": "Redirects"},
{"url": "", "label": "/test"},
],
response.content,
)
url_finder = AdminURLFinder(self.user)
expected_url = "/admin/redirects/%d/" % self.redirect.id
@ -1056,6 +1064,39 @@ class TestRedirectsEditView(WagtailTestUtils, TestCase):
# Should not redirect to index
self.assertEqual(response.status_code, 200)
def test_get_with_no_permission(self, redirect_id=None):
self.user.is_superuser = False
self.user.save()
# Only basic access_admin permission is given
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin",
codename="access_admin",
)
)
response = self.get()
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse("wagtailadmin_home"))
def test_get_with_edit_permission_only(self):
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin",
codename="access_admin",
),
Permission.objects.get(
content_type__app_label="wagtailredirects",
codename="change_redirect",
),
)
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailredirects/edit.html")
class TestRedirectsDeleteView(WagtailTestUtils, TestCase):
def setUp(self):

Wyświetl plik

@ -7,7 +7,7 @@ urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path("results/", views.IndexView.as_view(results_only=True), name="index_results"),
path("add/", views.add, name="add"),
path("<int:redirect_id>/", views.edit, name="edit"),
path("<int:redirect_id>/", views.EditView.as_view(), name="edit"),
path("<int:redirect_id>/delete/", views.delete, name="delete"),
path("import/", views.start_import, name="start_import"),
path("import/process/", views.process_import, name="process_import"),

Wyświetl plik

@ -136,49 +136,23 @@ class IndexView(generic.IndexView):
return buttons
@permission_checker.require("change")
def edit(request, redirect_id):
theredirect = get_object_or_404(models.Redirect, id=redirect_id)
class EditView(generic.EditView):
model = Redirect
form_class = RedirectForm
permission_policy = permission_policy
template_name = "wagtailredirects/edit.html"
index_url_name = "wagtailredirects:index"
edit_url_name = "wagtailredirects:edit"
delete_url_name = "wagtailredirects:delete"
pk_url_kwarg = "redirect_id"
error_message = gettext_lazy("The redirect could not be saved due to errors.")
header_icon = "redirect"
_show_breadcrumbs = True
if not permission_policy.user_has_permission_for_instance(
request.user, "change", theredirect
):
raise PermissionDenied
if request.method == "POST":
form = RedirectForm(request.POST, request.FILES, instance=theredirect)
if form.is_valid():
with transaction.atomic():
form.save()
log(instance=theredirect, action="wagtail.edit")
messages.success(
request,
_("Redirect '%(redirect_title)s' updated.")
% {"redirect_title": theredirect.title},
buttons=[
messages.button(
reverse("wagtailredirects:edit", args=(theredirect.id,)),
_("Edit"),
)
],
)
return redirect("wagtailredirects:index")
else:
messages.error(request, _("The redirect could not be saved due to errors."))
else:
form = RedirectForm(instance=theredirect)
return TemplateResponse(
request,
"wagtailredirects/edit.html",
{
"redirect": theredirect,
"form": form,
"user_can_delete": permission_policy.user_has_permission(
request.user, "delete"
),
},
)
def get_success_message(self):
return _("Redirect '%(redirect_title)s' updated.") % {
"redirect_title": self.object.title
}
@permission_checker.require("delete")

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -21,6 +21,9 @@ msgstr ""
"Language: hi\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "default"
msgstr "मूलचर"
#, python-format
msgid "%(site_setting)s for %(site)s"
msgstr "%(site_setting)s for %(site)s"

Wyświetl plik

@ -14,6 +14,7 @@ from wagtail.test.testapp.models import (
PanelGenericSettings,
TabbedGenericSettings,
TestGenericSetting,
TestPermissionedGenericSetting,
)
from wagtail.test.utils import WagtailTestUtils
@ -76,6 +77,11 @@ class BaseTestGenericSettingView(WagtailTestUtils, TestCase):
class TestGenericSettingCreateView(BaseTestGenericSettingView):
def setUp(self):
self.user = self.login()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
)
)
def test_get_edit(self):
response = self.get()
@ -107,6 +113,38 @@ class TestGenericSettingCreateView(BaseTestGenericSettingView):
# Ensure the form supports file uploads
self.assertContains(response, 'enctype="multipart/form-data"')
def test_create_restricted_field_without_permission(self):
self.user.is_superuser = False
self.user.save()
self.assertFalse(TestPermissionedGenericSetting.objects.exists())
response = self.post(
post_data={"sensitive_email": "test@example.com", "title": "test"},
setting=TestPermissionedGenericSetting,
)
self.assertEqual(response.status_code, 302)
settings = TestPermissionedGenericSetting.objects.get()
self.assertEqual(settings.title, "test")
self.assertEqual(settings.sensitive_email, "")
def test_create_restricted_field(self):
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(codename="can_edit_sensitive_email_generic_setting")
)
self.assertFalse(TestPermissionedGenericSetting.objects.exists())
response = self.post(
post_data={"sensitive_email": "test@example.com", "title": "test"},
setting=TestPermissionedGenericSetting,
)
self.assertEqual(response.status_code, 302)
settings = TestPermissionedGenericSetting.objects.get()
self.assertEqual(settings.title, "test")
self.assertEqual(settings.sensitive_email, "test@example.com")
class TestGenericSettingEditView(BaseTestGenericSettingView):
def setUp(self):
@ -114,7 +152,12 @@ class TestGenericSettingEditView(BaseTestGenericSettingView):
self.test_setting.title = "Setting title"
self.test_setting.save()
self.login()
self.user = self.login()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
)
)
def test_get_edit(self):
response = self.get()
@ -162,6 +205,50 @@ class TestGenericSettingEditView(BaseTestGenericSettingView):
expected_url=f"{url}{TestGenericSetting.objects.first().pk}/",
)
def test_edit_restricted_field(self):
test_setting = TestPermissionedGenericSetting()
test_setting.sensitive_email = "test@example.com"
test_setting.save()
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(codename="can_edit_sensitive_email_generic_setting")
)
response = self.get(setting=TestPermissionedGenericSetting)
self.assertEqual(response.status_code, 200)
self.assertIn("sensitive_email", list(response.context["form"].fields))
response = self.post(
setting=TestPermissionedGenericSetting,
post_data={"sensitive_email": "test-updated@example.com", "title": "title"},
)
self.assertEqual(response.status_code, 302)
test_setting.refresh_from_db()
self.assertEqual(test_setting.sensitive_email, "test-updated@example.com")
def test_edit_restricted_field_without_permission(self):
test_setting = TestPermissionedGenericSetting()
test_setting.sensitive_email = "test@example.com"
test_setting.save()
self.user.is_superuser = False
self.user.save()
response = self.get(setting=TestPermissionedGenericSetting)
self.assertEqual(response.status_code, 200)
self.assertNotIn("sensitive_email", list(response.context["form"].fields))
response = self.post(
setting=TestPermissionedGenericSetting,
post_data={"sensitive_email": "test-updated@example.com", "title": "title"},
)
self.assertEqual(response.status_code, 302)
test_setting.refresh_from_db()
self.assertEqual(test_setting.sensitive_email, "test@example.com")
class TestAdminPermission(WagtailTestUtils, TestCase):
def test_registered_permission(self):

Wyświetl plik

@ -14,6 +14,7 @@ from wagtail.test.testapp.models import (
IconSiteSetting,
PanelSiteSettings,
TabbedSiteSettings,
TestPermissionedSiteSetting,
TestSiteSetting,
)
from wagtail.test.utils import WagtailTestUtils
@ -72,6 +73,11 @@ class BaseTestSiteSettingView(WagtailTestUtils, TestCase):
class TestSiteSettingCreateView(BaseTestSiteSettingView):
def setUp(self):
self.user = self.login()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
)
)
def test_get_edit(self):
response = self.get()
@ -103,18 +109,55 @@ class TestSiteSettingCreateView(BaseTestSiteSettingView):
# Ensure the form supports file uploads
self.assertContains(response, 'enctype="multipart/form-data"')
def test_create_restricted_field_without_permission(self):
self.user.is_superuser = False
self.user.save()
self.assertFalse(TestPermissionedSiteSetting.objects.exists())
response = self.post(
post_data={"sensitive_email": "test@example.com", "title": "test"},
setting=TestPermissionedSiteSetting,
)
self.assertEqual(response.status_code, 302)
settings = TestPermissionedSiteSetting.objects.get()
self.assertEqual(settings.title, "test")
self.assertEqual(settings.sensitive_email, "")
def test_create_restricted_field(self):
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(codename="can_edit_sensitive_email_site_setting")
)
self.assertFalse(TestPermissionedSiteSetting.objects.exists())
response = self.post(
post_data={"sensitive_email": "test@example.com", "title": "test"},
setting=TestPermissionedSiteSetting,
)
self.assertEqual(response.status_code, 302)
settings = TestPermissionedSiteSetting.objects.get()
self.assertEqual(settings.title, "test")
self.assertEqual(settings.sensitive_email, "test@example.com")
class TestSiteSettingEditView(BaseTestSiteSettingView):
def setUp(self):
default_site = Site.objects.get(is_default_site=True)
self.default_site = Site.objects.get(is_default_site=True)
self.test_setting = TestSiteSetting()
self.test_setting.title = "Site title"
self.test_setting.email = "initial@example.com"
self.test_setting.site = default_site
self.test_setting.site = self.default_site
self.test_setting.save()
self.login()
self.user = self.login()
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
)
)
def test_get_edit(self):
response = self.get()
@ -167,6 +210,52 @@ class TestSiteSettingEditView(BaseTestSiteSettingView):
response = self.client.get(url)
self.assertRedirects(response, status_code=302, expected_url="/admin/")
def test_edit_restricted_field(self):
test_setting = TestPermissionedSiteSetting()
test_setting.sensitive_email = "test@example.com"
test_setting.site = self.default_site
test_setting.save()
self.user.is_superuser = False
self.user.save()
self.user.user_permissions.add(
Permission.objects.get(codename="can_edit_sensitive_email_site_setting")
)
response = self.get(setting=TestPermissionedSiteSetting)
self.assertEqual(response.status_code, 200)
self.assertIn("sensitive_email", list(response.context["form"].fields))
response = self.post(
setting=TestPermissionedSiteSetting,
post_data={"sensitive_email": "test-updated@example.com", "title": "title"},
)
self.assertEqual(response.status_code, 302)
test_setting.refresh_from_db()
self.assertEqual(test_setting.sensitive_email, "test-updated@example.com")
def test_edit_restricted_field_without_permission(self):
test_setting = TestPermissionedSiteSetting()
test_setting.sensitive_email = "test@example.com"
test_setting.site = self.default_site
test_setting.save()
self.user.is_superuser = False
self.user.save()
response = self.get(setting=TestPermissionedSiteSetting)
self.assertEqual(response.status_code, 200)
self.assertNotIn("sensitive_email", list(response.context["form"].fields))
response = self.post(
setting=TestPermissionedSiteSetting,
post_data={"sensitive_email": "test-updated@example.com", "title": "title"},
)
self.assertEqual(response.status_code, 302)
test_setting.refresh_from_db()
self.assertEqual(test_setting.sensitive_email, "test@example.com")
@override_settings(
ALLOWED_HOSTS=["testserver", "example.com", "noneoftheabove.example.com"]

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -1,6 +1,7 @@
from django.test import TestCase
from django.urls import reverse
from wagtail.admin.staticfiles import versioned_static
from wagtail.test.utils import WagtailTestUtils
@ -13,3 +14,10 @@ class TestStyleGuide(WagtailTestUtils, TestCase):
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailstyleguide/base.html")
custom_css = versioned_static("wagtailstyleguide/css/animate-progress.css")
widget_css = versioned_static("wagtailadmin/css/panels/draftail.css")
widget_js = versioned_static("wagtailadmin/js/draftail.js")
self.assertContains(response, custom_css)
self.assertContains(response, widget_css)
self.assertContains(response, widget_js)

Wyświetl plik

@ -94,7 +94,7 @@ class ExampleForm(forms.Form):
@property
def media(self):
return forms.Media(
return super().media + forms.Media(
css={
"all": [versioned_static("wagtailstyleguide/css/animate-progress.css")]
}

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -610,23 +610,23 @@ msgid_plural "%(num_parent_objects)d images have been deleted"
msgstr[0] ""
msgstr[1] ""
#: views/chooser.py:51 views/chooser.py:313
#: views/chooser.py:51 views/chooser.py:314
msgid "Upload"
msgstr ""
#: views/chooser.py:52 views/chooser.py:314
#: views/chooser.py:52 views/chooser.py:315
msgid "Uploading…"
msgstr ""
#: views/chooser.py:312 widgets.py:13
#: views/chooser.py:313 widgets.py:13
msgid "Choose an image"
msgstr ""
#: views/chooser.py:315
#: views/chooser.py:316
msgid "Choose another image"
msgstr ""
#: views/chooser.py:316 widgets.py:15
#: views/chooser.py:317 widgets.py:15
msgid "Edit this image"
msgstr ""

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -317,6 +317,23 @@ msgstr "Scegli un formato"
msgid "Insert image"
msgstr "Inserisci immagine"
#, python-format
msgid ""
"<span>%(total)s</span> Image <span class=\"w-sr-only\">created in "
"%(site_name)s</span>"
msgid_plural ""
"<span>%(total)s</span> Images <span class=\"w-sr-only\">created in "
"%(site_name)s</span>"
msgstr[0] ""
"<span>%(total)s</span> immagine <span class=\"w-sr-only\">creata in "
"%(site_name)s</span>"
msgstr[1] ""
"<span>%(total)s</span> immagini <span class=\"w-sr-only\">create in "
"%(site_name)s</span>"
msgstr[2] ""
"<span>%(total)s</span> immagini <span class=\"w-sr-only\">create in "
"%(site_name)s</span>"
msgid "Change image file:"
msgstr "Cambia immagine"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -75,6 +75,9 @@ msgstr "Wagtail cache frontend"
msgid "Wagtail sitemaps"
msgstr "Sitemap Wagtail"
msgid "Unknown content type"
msgstr "Tipo contenuto sconosciuto"
msgid "Password"
msgstr "Password"
@ -87,6 +90,28 @@ msgstr "Commenta"
msgid "Locked"
msgstr "Bloccata"
#, python-format
msgid "No one can make changes while the %(model_name)s is locked"
msgstr "Nessuno può fare modifiche finché %(model_name)s è bloccato"
#, python-brace-format
msgid "<b>'{title}' was locked</b> by <b>you</b> on <b>{datetime}</b>."
msgstr "<b>'{title}' è stata bloccata</b> da <b>te</b> il <b>{datetime}</b>."
#, python-brace-format
msgid "<b>'{title}' is locked</b> by <b>you</b>."
msgstr "<b>'{title}' è bloccata</b> da <b>te</b>."
#, python-brace-format
msgid "<b>'{title}' is locked</b>."
msgstr "<b>'{title}' è bloccata</b>."
msgid "Locked by you"
msgstr "Bloccata da te"
msgid "Locked by another user"
msgstr "Bloccata da un altro utente"
msgid "Unlocked"
msgstr "Sbloccata"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -0,0 +1,43 @@
from django.apps import apps
from django.core.management.base import BaseCommand
from django.db import connection, models
from wagtail.models import (
BaseLogEntry,
BootstrapTranslatableMixin,
ReferenceIndex,
TranslatableMixin,
)
class Command(BaseCommand):
help = "Converts UUID columns from char type to the native UUID type used in MariaDB 10.7+ and Django 5.0+."
def convert_field(self, model, field_name, null=False):
if model._meta.get_field(field_name).model != model:
# Field is inherited from a parent model
return
if not model._meta.managed:
# The migration framework skips unmanaged models, so we should too
return
old_field = models.CharField(null=null, max_length=36)
old_field.set_attributes_from_name(field_name)
new_field = models.UUIDField(null=null)
new_field.set_attributes_from_name(field_name)
with connection.schema_editor() as schema_editor:
schema_editor.alter_field(model, old_field, new_field)
def handle(self, **options):
self.convert_field(ReferenceIndex, "content_path_hash")
for model in apps.get_models():
if issubclass(model, BaseLogEntry):
self.convert_field(model, "uuid", null=True)
elif issubclass(model, BootstrapTranslatableMixin):
self.convert_field(model, "translation_key", null=True)
elif issubclass(model, TranslatableMixin):
self.convert_field(model, "translation_key")

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -182,7 +182,7 @@ msgstr ""
msgid "Choose"
msgstr ""
#: views/snippets.py:77 views/snippets.py:104 views/snippets.py:913
#: views/snippets.py:77 views/snippets.py:104 views/snippets.py:894
#: wagtail_hooks.py:44
msgid "Snippets"
msgstr ""
@ -200,17 +200,17 @@ msgstr ""
msgid "More options for '%(title)s'"
msgstr ""
#: views/snippets.py:389
#: views/snippets.py:370
#, python-format
msgid "Edit this %(model_name)s"
msgstr ""
#: views/snippets.py:395
#: views/snippets.py:376
#, python-format
msgid "%(model_name)s history"
msgstr ""
#: views/snippets.py:912
#: views/snippets.py:893
msgid "Home"
msgstr ""

Wyświetl plik

@ -233,22 +233,6 @@ class CreateView(generic.CreateEditViewOptionalFeaturesMixin, generic.CreateView
def _get_action_menu(self):
return SnippetActionMenu(self.request, view=self.view_name, model=self.model)
def _get_initial_form_instance(self):
instance = self.model()
# Set locale of the new instance
if self.locale:
instance.locale = self.locale
return instance
def get_form_kwargs(self):
return {
**super().get_form_kwargs(),
"instance": self._get_initial_form_instance(),
"for_user": self.request.user,
}
def get_side_panels(self):
side_panels = [
SnippetStatusSidePanel(
@ -308,9 +292,6 @@ class EditView(generic.CreateEditViewOptionalFeaturesMixin, generic.EditView):
locked_for_user=self.locked_for_user,
)
def get_form_kwargs(self):
return {**super().get_form_kwargs(), "for_user": self.request.user}
def get_side_panels(self):
side_panels = [
SnippetStatusSidePanel(

Wyświetl plik

@ -3,6 +3,7 @@ from django.shortcuts import resolve_url
from django.template.defaulttags import token_kwargs
from django.template.loader import render_to_string
from django.utils.encoding import force_str
from django.utils.functional import Promise
from django.utils.html import conditional_escape
from wagtail import VERSION, __version__
@ -120,6 +121,8 @@ def richtext(value):
elif value is None:
html = ""
else:
if isinstance(value, Promise):
value = str(value)
if isinstance(value, str):
html = expand_db_html(value)
else:

Wyświetl plik

@ -0,0 +1,42 @@
# Generated by Django 4.2.11 on 2024-04-25 15:51
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0093_uploadedfile'),
('tests', '0036_complexdefaultstreampage'),
]
operations = [
migrations.CreateModel(
name='TestPermissionedGenericSetting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('sensitive_email', models.EmailField(max_length=50)),
],
options={
'permissions': [('can_edit_sensitive_email_generic_setting', 'Can edit sensitive email generic setting.')],
},
),
migrations.AlterModelOptions(
name='featurecompletetoy',
options={'permissions': [('can_set_release_date', 'Can set release date')]},
),
migrations.CreateModel(
name='TestPermissionedSiteSetting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('sensitive_email', models.EmailField(max_length=50)),
('site', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='wagtailcore.site')),
],
options={
'permissions': [('can_edit_sensitive_email_site_setting', 'Can edit sensitive email site setting.')],
},
),
]

Wyświetl plik

@ -1685,6 +1685,49 @@ class TestGenericSetting(BaseGenericSetting):
email = models.EmailField(max_length=50)
@register_setting
class TestPermissionedGenericSetting(BaseGenericSetting):
title = models.CharField(max_length=100)
sensitive_email = models.EmailField(max_length=50)
panels = [
FieldPanel("title"),
FieldPanel(
"sensitive_email",
permission="tests.can_edit_sensitive_email_generic_setting",
),
]
class Meta:
permissions = [
(
"can_edit_sensitive_email_generic_setting",
"Can edit sensitive email generic setting.",
),
]
@register_setting
class TestPermissionedSiteSetting(BaseSiteSetting):
title = models.CharField(max_length=100)
sensitive_email = models.EmailField(max_length=50)
panels = [
FieldPanel("title"),
FieldPanel(
"sensitive_email", permission="tests.can_edit_sensitive_email_site_setting"
),
]
class Meta:
permissions = [
(
"can_edit_sensitive_email_site_setting",
"Can edit sensitive email site setting.",
),
]
@register_setting
class ImportantPagesSiteSetting(BaseSiteSetting):
sign_up_page = models.ForeignKey(
@ -2274,6 +2317,9 @@ class FeatureCompleteToy(index.Indexed, models.Model):
def __str__(self):
return f"{self.name} ({self.release_date})"
class Meta:
permissions = [("can_set_release_date", "Can set release date")]
class PurgeRevisionsProtectedTestModel(models.Model):
revision = models.OneToOneField(

Wyświetl plik

@ -229,7 +229,7 @@ class FeatureCompleteToyViewSet(ModelViewSet):
panels = [
FieldPanel("name"),
FieldPanel("release_date"),
FieldPanel("release_date", permission="tests.can_set_release_date"),
]

Wyświetl plik

@ -9,6 +9,7 @@ from django.test import TestCase
from django.test.utils import override_settings
from django.urls.exceptions import NoReverseMatch
from django.utils.safestring import SafeString
from django.utils.translation import gettext_lazy
from wagtail.coreutils import (
get_dummy_request,
@ -536,6 +537,10 @@ class TestRichtextTag(TestCase):
self.assertEqual(result, "Hello world!")
self.assertIsInstance(result, SafeString)
def test_call_with_lazy(self):
result = richtext(gettext_lazy("test"))
self.assertEqual(result, "test")
def test_call_with_none(self):
result = richtext(None)
self.assertEqual(result, "")

Wyświetl plik

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"POT-Creation-Date: 2024-05-02 10:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -160,15 +160,16 @@ msgstr ""
msgid "Snug"
msgstr ""
#: models.py:92
#. Translators: "Density" is the term used to describe the amount of space between elements in the user interface
#: models.py:93
msgid "density"
msgstr ""
#: models.py:112
#: models.py:113
msgid "user profile"
msgstr ""
#: models.py:113
#: models.py:114
msgid "user profiles"
msgstr ""

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -6,7 +6,7 @@
# Giacomo Ghizzani <giacomo.ghz@gmail.com>, 2015-2018
# giammi <gian-maria.daffre@giammi.org>, 2018
# giammi <gian-maria.daffre@giammi.org>, 2018
# Marco Badan <marco.badan@gmail.com>, 2021-2023
# Marco Badan <marco.badan@gmail.com>, 2021-2024
# Sandro Badalamenti <sandro@mailinator.com>, 2019
msgid ""
msgstr ""
@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
"PO-Revision-Date: 2014-02-19 11:54+0000\n"
"Last-Translator: Marco Badan <marco.badan@gmail.com>, 2021-2023\n"
"Last-Translator: Marco Badan <marco.badan@gmail.com>, 2021-2024\n"
"Language-Team: Italian (http://app.transifex.com/torchbox/wagtail/language/"
"it/)\n"
"MIME-Version: 1.0\n"
@ -132,6 +132,12 @@ msgstr "tema admin"
msgid "Default"
msgstr "Default"
msgid "Snug"
msgstr "Compatta"
msgid "density"
msgstr "densità"
msgid "user profile"
msgstr "profilo utente"
@ -265,6 +271,30 @@ msgstr "Sblocca"
msgid "Custom permissions"
msgstr "Permessi personalizzati"
msgid "Toggle all"
msgstr "Attiva/disattiva tutto"
msgid "Toggle all add permissions"
msgstr "Attiva/disattiva tutti i permessi di aggiunta"
msgid "Toggle all change permissions"
msgstr "Attiva/disattiva tutti i permessi di modifica"
msgid "Toggle all delete permissions"
msgstr "Attiva/disattiva tutti i permessi di eliminazione"
msgid "Toggle all publish permissions"
msgstr "Attiva/disattiva tutti i permessi di pubblicazione"
msgid "Toggle all lock permissions"
msgstr "Attiva/disattiva tutti i permessi di blocco"
msgid "Toggle all unlock permissions"
msgstr "Attiva/disattiva tutti i permessi di sblocco"
msgid "Toggle all custom permissions"
msgstr "Attiva/disattiva tutti i permessi personalizzati"
msgid "Other permissions"
msgstr "Altri permessi"
@ -307,6 +337,9 @@ msgstr "Elimina utente"
msgid "Select all users in listing"
msgstr "Seleziona tutti gli utenti nella lista"
msgid "Sorry, no users match your query"
msgstr "Nessun utente corrisponde alla tua ricerca"
#, python-format
msgid ""
"There are no users configured. Why not <a "
@ -395,6 +428,9 @@ msgstr "Visualizza utenti in questo gruppo"
msgid "Group '%(object)s' deleted."
msgstr "Gruppo '%(object)s' eliminato."
msgid "Last login"
msgstr "Ultimo accesso"
msgid "Group"
msgstr "Gruppo"

Wyświetl plik

@ -89,6 +89,7 @@ class UserProfile(models.Model):
SNUG = "snug", _("Snug")
density = models.CharField(
# Translators: "Density" is the term used to describe the amount of space between elements in the user interface
verbose_name=_("density"),
choices=AdminDensityThemes.choices,
default=AdminDensityThemes.DEFAULT,