Update docs and changelog to reflect changes for #9817

pull/9817/head
Sage Abdullah 2023-01-19 14:05:42 +00:00
rodzic 5f4a2ed38d
commit ad3ef5875d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: EB1A33CC51CC0217
4 zmienionych plików z 105 dodań i 27 usunięć

Wyświetl plik

@ -30,6 +30,7 @@ Changelog
* Make the rich text block trigger and slash-commands always available regardless of where the cursor is (Thibaud Colas)
* Adjust the size of panel labels on the "Account" form (Thibaud Colas)
* Delay hiding the contents of the side panels when closing, so the animation is smoother (Thibaud Colas)
* Added ability to submit snippets for moderation with `WorkflowMixin` (Sage Abdullah)
* Fix: Make sure workflow timeline icons are visible in high-contrast mode (Loveth Omokaro)
* Fix: Ensure authentication forms (login, password reset) have a visible border in Windows high-contrast mode (Loveth Omokaro)
* Fix: Ensure visual consistency between buttons and links as buttons in Windows high-contrast mode (Albina Starykova)
@ -75,6 +76,11 @@ Changelog
* Fix: Prevent memory exhaustion when purging a large number of revisions (Jake Howard)
* Fix: Add right-to-left (RTL) support for the following form components: Switch, Minimap, live preview (Thibaud Colas)
* Fix: Improve right-to-left (RTL) positioning for the following components: Page explorer, Sidebar sub-menu, rich text tooltips, rich text toolbar trigger, editor section headers (Thibaud Colas)
* Fix: Use the workflow name as the workflow information dialog title (Sage Abdullah)
* Fix: Link to workflow history view instead of page history view in the workflow information dialog (Sage Abdullah)
* Fix: Fix in-progress count in warning message when disabling workflows (Sage Abdullah)
* Fix: Show workflow name on workflow history index page (Sage Abdullah)
* Fix: Fix workflow history detail timeline content from showing on initial load (Sage Abdullah)
* Docs: Add custom permissions section to permissions documentation page (Dan Hayden)
* Docs: Add documentation for how to get started with contributing translations for the Wagtail admin (Ogunbanjo Oluwadamilare)
* Docs: Officially recommend `fnm` over `nvm` in development documentation (LB (Ben) Johnston)

Wyświetl plik

@ -85,7 +85,7 @@ class UserApprovalTask(Task):
## Custom TaskState models
You might also need to store custom state information for the task: for example, a rating left by an approving user.
Normally, this is done on an instance of `TaskState`, which is created when a page starts the task. However, this can
Normally, this is done on an instance of `TaskState`, which is created when an object starts the task. However, this can
also be subclassed equivalently to `Task`:
```python
@ -124,26 +124,30 @@ class UserApprovalTask(Task):
Both `Task` and `TaskState` have a number of methods that can be overridden to implement custom behaviour. Here are some of the most useful:
`Task.user_can_access_editor(page, user)`, `Task.user_can_lock(page, user)`, `Task.user_can_unlock(page, user)`:
`Task.user_can_access_editor(obj, user)`, `Task.user_can_lock(obj, user)`, `Task.user_can_unlock(obj, user)`:
These methods determine if users usually without permission can access the editor, and lock, or unlock the page, by returning True or False.
These methods determine if users usually without permission can access the editor, and lock, or unlock the object, by returning True or False.
Note that returning `False` will not prevent users who would normally be able to perform those actions. For example, for our `UserApprovalTask`:
```python
def user_can_access_editor(self, page, user):
def user_can_access_editor(self, obj, user):
return user == self.user
```
`Task.page_locked_for_user(page, user)`:
`Task.locked_for_user(obj, user)`:
This returns `True` if the page should be locked and uneditable by the user. It is used by `GroupApprovalTask` to lock the page to any users not in the approval group.
This returns `True` if the object should be locked and uneditable by the user. It is used by `GroupApprovalTask` to lock the object to any users not in the approval group.
```python
def page_locked_for_user(self, page, user):
def locked_for_user(self, obj, user):
return user != self.user
```
`Task.get_actions(page, user)`:
```{versionchanged} 4.2
This method was previously named ``page_locked_for_user``, using ``page_locked_for_user`` will be removed in a future release. Along with the other similar methods, the ``obj`` parameter was previously named ``page``.
```
`Task.get_actions(obj, user)`:
This returns a list of `(action_name, action_verbose_name, action_requires_additional_data_from_modal)` tuples, corresponding to the actions available for the task in the edit view menu.
`action_requires_additional_data_from_modal` should be a boolean, returning `True` if choosing the action should open a modal for additional data input - for example, entering a comment.
@ -151,7 +155,7 @@ This returns a list of `(action_name, action_verbose_name, action_requires_addit
For example:
```python
def get_actions(self, page, user):
def get_actions(self, obj, user):
if user == self.user:
return [
('approve', "Approve", False),
@ -172,7 +176,7 @@ Returns the name of a custom template to be used in rendering the data entry mod
`Task.on_action(task_state, user, action_name, **kwargs)`:
This performs the actions specified in `Task.get_actions(page, user)`: it is passed an action name, for example, `approve`, and the relevant task state. By default, it calls `approve` and `reject` methods on the task state when the corresponding action names are passed through. Any additional data entered in a modal (see `get_form_for_action` and `get_actions`) is supplied as kwargs.
This performs the actions specified in `Task.get_actions(obj, user)`: it is passed an action name, for example, `approve`, and the relevant task state. By default, it calls `approve` and `reject` methods on the task state when the corresponding action names are passed through. Any additional data entered in a modal (see `get_form_for_action` and `get_actions`) is supplied as kwargs.
For example, let's say we wanted to add an additional option: cancelling the entire workflow:
@ -186,7 +190,7 @@ def on_action(self, task_state, user, action_name):
`Task.get_task_states_user_can_moderate(user, **kwargs)`:
This returns a QuerySet of `TaskStates` (or subclasses) the given user can moderate - this is currently used to select pages to display on the user's dashboard.
This returns a QuerySet of `TaskStates` (or subclasses) the given user can moderate - this is currently used to select objects to display on the user's dashboard.
For example:
@ -237,13 +241,13 @@ class BaseUserApprovalTaskStateEmailNotifier(EmailNotificationMixin, Notifier):
def can_handle(self, instance, **kwargs):
if super().can_handle(instance, **kwargs) and isinstance(instance.task.specific, UserApprovalTask):
# Don't send notifications if a Task has been cancelled and then resumed - when page was updated to a new revision
# Don't send notifications if a Task has been cancelled and then resumed - when object was updated to a new revision
return not TaskState.objects.filter(workflow_state=instance.workflow_state, task=instance.task, status=TaskState.STATUS_CANCELLED).exists()
return False
def get_context(self, task_state, **kwargs):
context = super().get_context(task_state, **kwargs)
context['page'] = task_state.workflow_state.page
context['object'] = task_state.workflow_state.content_object
context['task'] = task_state.task.specific
return context

Wyświetl plik

@ -645,10 +645,10 @@ The model is added to allow snippets to be locked. See [](wagtailsnippets_lockin
## `WorkflowMixin`
`WorkflowMixin` is a mixin class that can be added to any non-page Django model to allow its instances to be submitted to workflows.
This mixin requires {class}`~wagtail.models.RevisionMixin`, {class}`~wagtail.models.DraftStateMixin`, and {class}`~wagtail.models.LockableMixin` to be applied. Pages already include this mixin, so there is no need to add it.
This mixin requires {class}`~wagtail.models.RevisionMixin` and {class}`~wagtail.models.DraftStateMixin` to be applied. Pages already include this mixin, so there is no need to add it.
```{versionadded} 4.2
The model is added to allow snippets to be submitted to workflows. See [](wagtailsnippets_enabling_workflows) for more details.
The model is added to allow snippets to be submitted for moderation. See [](wagtailsnippets_enabling_workflows) for more details.
```
### Methods and properties
@ -873,7 +873,7 @@ The model has been renamed from ``PageRevision`` to ``Revision`` and it now refe
## `Workflow`
Workflows represent sequences of tasks which much be approved for an action to be performed on a page - typically publication.
Workflows represent sequences of tasks which must be approved for an action to be performed on an object - typically publication.
### Database fields
@ -890,7 +890,7 @@ Workflows represent sequences of tasks which much be approved for an action to b
(boolean)
Whether or not the workflow is active: active workflows can be added to pages, and started. Inactive workflows cannot.
Whether or not the workflow is active: active workflows can be added to pages and snippets, and started. Inactive workflows cannot.
```
### Methods and properties
@ -910,18 +910,40 @@ Workflows represent sequences of tasks which much be approved for an action to b
## `WorkflowState`
Workflow states represent the status of a started workflow on a page.
Workflow states represent the status of a started workflow on an object.
### Database fields
```{eval-rst}
.. class:: WorkflowState
.. attribute:: page
.. attribute:: content_object
(foreign key to ``Page``)
(generic foreign key)
The page on which the workflow has been started
The object on which the workflow has been started. For page workflows, the object is an instance of the base ``Page`` model.
.. versionchanged:: 4.2
This field has been changed from a ``ForeignKey`` to ``Page`` into a :class:`~django.contrib.contenttypes.fields.GenericForeignKey` to any Django model instance.
.. attribute:: content_type
(foreign key to :class:`~django.contrib.contenttypes.models.ContentType`)
The content type of the object this workflow state belongs to. For page workflows, this means the content type of the specific page type.
.. attribute:: base_content_type
(foreign key to :class:`~django.contrib.contenttypes.models.ContentType`)
The base content type of the object this workflow state belongs to. For page workflows, this means the content type of the :class:`~wagtail.models.Page` model.
.. attribute:: object_id
(string)
The primary key of the object this revision belongs to.
.. attribute:: workflow
@ -1056,7 +1078,7 @@ Tasks represent stages in a workflow which must be approved for the workflow to
## `TaskState`
Task states store state information about the progress of a task on a particular page revision.
Task states store state information about the progress of a task on a particular revision.
### Database fields
@ -1065,19 +1087,23 @@ Task states store state information about the progress of a task on a particular
.. attribute:: workflow_state
(foreign key to ``WorkflowState``)
(foreign key to :class:`~wagtail.models.WorkflowState`)
The workflow state which started this task state.
.. attribute:: revision
(foreign key to ``Revision``)
(foreign key to :class:`~wagtail.models.Revision`)
The revision this task state was created on.
.. versionchanged:: 4.2
This field has been renamed from ``page_revision`` to ``revision``.
.. attribute:: task
(foreign key to ``Task``)
(foreign key to :class:`~wagtail.models.Task`)
The task that this task state is storing state information for.
@ -1183,11 +1209,32 @@ Represents the assignment of a workflow to a page and its descendants.
.. attribute:: workflow
(foreign key to ``Workflow``)
(foreign key to :class:`~wagtail.models.Workflow`)
.. attribute:: page
(foreign key to ``Page``)
(foreign key to :class:`~wagtail.models.Page`)
```
## `WorkflowContentType`
Represents the assignment of a workflow to a Django model.
### Database fields
```{eval-rst}
.. class:: WorkflowContentType
.. attribute:: workflow
(foreign key to :class:`~wagtail.models.Workflow`)
.. attribute:: content_type
(foreign key to :class:`~django.contrib.contenttypes.models.ContentType`)
A foreign key to the ``ContentType`` object that represents the model that is assigned to the workflow.
```
## `BaseLogEntry`

Wyświetl plik

@ -21,6 +21,12 @@ Snippets can now be locked by users to prevent other users from editing, through
This feature was developed by Sage Abdullah.
### Workflows for snippets
Snippets can now be assigned to workflows through the use of the `WorkflowMixin`, allowing new changes to be submitted for moderation before they are published. For more details, see [](wagtailsnippets_enabling_workflows).
This feature was developed by Sage Abdullah.
### `fullpageurl` template tag
Wagtail now provides a `fullpageurl` template tag (for both Django templates and Jinja2) to output a page's full URL including the domain. For more details, see [](fullpageurl_tag).
@ -245,3 +251,18 @@ If you are using the front-end cache invalidator module (`wagtail.contrib.fronte
* For Azure Front Door: upgrade `azure-mgmt-frontdoor` to version 1 or above
Support for older versions will be dropped in a future release.
### Changes to `Workflow` and `Task` methods
To accommodate workflows support for snippets, the `page` parameter in {meth}`Workflow.start() <wagtail.models.Workflow.start>` has been renamed to `obj`.
In addition, some methods on the base {class}`~wagtail.models.Task` model have been changed. If you have {doc}`custom Task types </extending/custom_tasks>`, make sure to update the methods to reflect the following changes:
- `page_locked_for_user()` is now {meth}`~wagtail.models.Task.locked_for_user`. Using `page_locked_for_user()` is deprecated and will be removed in a future release.
- The `page` parameter in `user_can_access_editor()`, `locked_for_user()`, `user_can_lock()`, `user_can_unlock()`, `get_actions()`, has been renamed to `obj`.
### Changes to `WorkflowState` and `TaskState` models
To accommodate workflows support for snippets, the `WorkflowState.page` foreign key has been replaced with a `GenericForeignKey` as `WorkflowState.content_object`. The generic foreign key is defined using a combination of the new `WorkflowState.base_content_type` and `WorkflowState.object_id` fields.
The `TaskState.page_revision` foreign key has been renamed to `TaskState.revision`.