From c79668929ebb7871c6b23f7aa01c6af7b9ee2bfb Mon Sep 17 00:00:00 2001 From: jacobtoppm Date: Thu, 16 Jul 2020 10:45:00 +0100 Subject: [PATCH] Update reference documentation, custom task guide, and release notes, and fix documentation build errors --- docs/advanced_topics/custom_tasks.rst | 40 ++++++++++++++++++------ docs/reference/pages/model_reference.rst | 35 +++++++++++++++++++-- docs/releases/2.10.rst | 2 +- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/docs/advanced_topics/custom_tasks.rst b/docs/advanced_topics/custom_tasks.rst index a191464571..29a02e8238 100644 --- a/docs/advanced_topics/custom_tasks.rst +++ b/docs/advanced_topics/custom_tasks.rst @@ -26,7 +26,7 @@ All custom tasks must be models inheriting from ``wagtailcore.Task``. In this se Subclassed Tasks follow the same approach as Pages: they are concrete models, with the specific subclass instance accessible by calling ``Task.specific()``. -You can now add any custom fields. To make these editable in the admin, add the names of the fields into the `admin_form_fields` attribute: +You can now add any custom fields. To make these editable in the admin, add the names of the fields into the ``admin_form_fields`` attribute: For example: @@ -67,7 +67,7 @@ can be added to ``admin_form_readonly_on_edit_fields``. For example: admin_form_readonly_on_edit_fields = Task.admin_form_readonly_on_edit_fields + ['user'] -Wagtail will choose a default form widget to use based on the field type. But you can override the form widget using the `admin_form_widgets` attribute: +Wagtail will choose a default form widget to use based on the field type. But you can override the form widget using the ``admin_form_widgets`` attribute: .. code-block:: python @@ -94,7 +94,7 @@ Wagtail will choose a default form widget to use based on the field type. But yo Custom TaskState models ~~~~~~~~~~~~~~~~~~~~~~~ -You might also need to store custom state information for the task: for example, a comment left by an approving user. +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 also be subclassed equivalently to ``Task``: @@ -146,9 +146,21 @@ Note that returning ``False`` will not prevent users who would normally be able def user_can_access_editor(self, page, user): return user == self.user +``Task.page_locked_for_user(page, 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. + +.. code-block:: python + + def page_locked_for_user(self, page, user): + return user != self.user + ``Task.get_actions(page, user)``: -This returns a list of ``(action_name, action_verbose_name)`` tuples, corresponding to the actions available for the task in the edit view menu. +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. For example: @@ -157,17 +169,27 @@ For example: def get_actions(self, page, user): if user == self.user: return [ - ('approve', "Approve"), - ('reject', "Reject"), - ('cancel', "Cancel"), + ('approve', "Approve", False), + ('reject', "Reject", False), + ('cancel', "Cancel", False), ] else: return [] -``Task.on_action(task_state, user, action_name)``: +``Task.get_form_for_action(action)``: + +Returns a form to be used for additional data input for the given action modal. By default, +returns ``TaskStateCommentForm``, with a single comment field. + +``Task.get_template_for_action(action)``: + +Returns the name of a custom template to be used in rendering the data entry modal for that action. + +``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, eg ``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. +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: diff --git a/docs/reference/pages/model_reference.rst b/docs/reference/pages/model_reference.rst index 7aac82e0f9..7b6d0fae6f 100644 --- a/docs/reference/pages/model_reference.rst +++ b/docs/reference/pages/model_reference.rst @@ -530,6 +530,8 @@ Methods and properties .. automethod:: deactivate + .. automethod:: all_pages + ``WorkflowState`` ================= @@ -586,7 +588,7 @@ Methods and properties .. attribute:: STATUS_CHOICES A tuple of the possible options for the ``status`` field, and their verbose names. Options are ``STATUS_IN_PROGRESS``, ``STATUS_APPROVED``, - ``STATUS_CANCELLED`` and ``STATUS_REJECTED``. + ``STATUS_CANCELLED`` and ``STATUS_NEEDS_CHANGES``. .. automethod:: update @@ -596,6 +598,8 @@ Methods and properties .. automethod:: finish + .. automethod:: resume + .. automethod:: copy_approved_task_states_to_revision .. automethod:: all_tasks_with_status @@ -639,6 +643,10 @@ Methods and properties .. class:: Task :noindex: + .. autoattribute:: workflows + + .. autoattribute:: active_workflows + .. attribute:: task_state_class The specific task state class to generate to store state information for this task. If not specified, this will be ``TaskState``. @@ -657,12 +665,20 @@ Methods and properties .. automethod:: user_can_unlock + .. automethod:: page_locked_for_user + .. automethod:: get_actions .. automethod:: get_task_states_user_can_moderate .. automethod:: deactivate + .. automethod:: get_form_for_action + + .. automethod:: get_template_for_action + + .. automethod:: get_description + ``TaskState`` ============= @@ -684,8 +700,7 @@ Database fields (foreign key to ``PageRevision``) - Whether or not the task is active: active workflows can be added to workflows, and started. Inactive workflows cannot, and are skipped when in - an existing workflow. + The page revision this task state was created on. .. attribute:: task @@ -717,6 +732,18 @@ Database fields When this task state was cancelled, rejected, or approved. + .. attribute:: finished_by + + (foreign key to user model) + + The user who completed (cancelled, rejected, approved) the task. + + .. attribute:: comment + + (text) + + A text comment, typically added by a user when the task is completed. + Methods and properties ~~~~~~~~~~~~~~~~~~~~~~ @@ -745,6 +772,8 @@ Methods and properties .. automethod:: copy + .. automethod:: get_comment + ``WorkflowTask`` ================ diff --git a/docs/releases/2.10.rst b/docs/releases/2.10.rst index d319853e31..3f9a16dd79 100644 --- a/docs/releases/2.10.rst +++ b/docs/releases/2.10.rst @@ -137,7 +137,7 @@ then chained together to form workflows: sequences of moderation stages through Key points: -* Prior to 2.9, moderation in Wagtail was performed on a per-revision basis: once submitted, the moderator would approve or reject +* Prior to 2.10, moderation in Wagtail was performed on a per-revision basis: once submitted, the moderator would approve or reject the submitted revision only, which would not include subsequent changes. Moderation is now performed per page, with moderators always seeing the latest revision. * ``PageRevision.submitted_for_moderation`` will return ``True`` for revisions passing through the old moderation system, but not for the new system