Task System¶
The task system lets editors assign work items (“tasks”) to other users or groups. A task is a piece of content stored in a per-user task container. Each user gets their own container, automatically created when their member area is set up. Tasks carry an initiator, one or more responsibles, an action, a due date, optional rich text, and an optional relation to a related content object.
The most common case – asking a colleague to review a specific page – is
exposed through the dedicated @task-review REST endpoint, which is a thin
shortcut around creating a task.
Overview¶
The system is built from two content types and a three-state workflow:
TaskContainer – a singleton folder living inside each user’s home folder (id
tasks). It is created automatically when a member area is created and on first login. It is excluded from navigation and cannot be moved or copied.Task – the actual work item, created inside a TaskContainer. Its title is derived from the action and the title of the related content (for example
review - My Page).
A task always has:
an initiator (defaults to the current user),
one or more responsibles (users and/or groups),
an action (chosen from a configurable vocabulary),
a due date (defaults to 14 days from creation),
optional rich text,
an optional related content relation.
When a task is created or modified, the responsible principals are granted the
Contributor role locally on the task, so they can see and work on it.
Actions¶
The set of available actions is configured in the registry record
wcs.backend.tasksystem.actions. It is a list of Title:value strings. The
shipped default is:
Information:info
Review:review
Aufgabe:task
The part before the colon is the human-readable title shown in the form; the part after the colon is the stored value. The first entry is used as the default action for a newly created task. To add or rename actions, edit this registry record.
Task Review Workflow¶
Tasks use the task_workflow. It has three states and is German-labelled:
State ( |
Title |
Meaning |
|---|---|---|
|
Offen |
Open, not started yet |
|
In Arbeit |
In progress |
|
Erledigt |
Done |
New tasks start in Offen. The available transitions are:
Offen → In Arbeit (
mit arbeit beginnen)Offen → Erledigt (
erledigen)In Arbeit → Erledigt (
erledigen)In Arbeit → Offen (
wieder eröffnen)Erledigt → Offen (
wieder eröffnen)
┌──────────────────────────────┐
│ │
▼ mit arbeit │ wieder
┌──────┐ beginnen ┌────────┐ eröffnen
│ Offen│ ───────────────────▶ │In Arbeit│
└──────┘ └────────┘
│ \ │
│ \ erledigen │ erledigen
│ \ ▼
│ \ ┌─────────┐
│ └────────────────▶│ Erledigt│
│ wieder └─────────┘
└────────────────────────────┘
eröffnen
All transitions are user-triggered and guarded by the Contributor, Manager,
and Owner roles – the responsibles of a task (who receive Contributor
locally) can therefore move it through the workflow.
Due Date Indexing¶
The due_date field is exposed to the catalog through a due_date indexer, so
tasks can be searched and sorted by their deadline.
REST API¶
POST @task-review¶
Creates a review task for the current context. This is a convenience wrapper
around posting a new Task into the current user’s task container. The endpoint
is available on any folderish content.
It takes the responsible(s) from the request body and fills in the rest automatically:
initiatoris set to the current user,relatedis set to the context the endpoint was called on,@typeis set toTask,actionis set toreview.
The responsible property is required; omitting it returns a 400 Bad Request. Any additional task fields (for example text or due_date) may be
passed in the body and are forwarded to the created task.
The created task is stored in the calling user’s task container, with the context page as its related content.
POST /Plone/topics/my-page/@task-review HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json
{
"responsible": ["user:editor1"],
"text": "<p>Please review the updated figures.</p>"
}
The response is the standard serialization of the newly created Task object.
Consuming @task-review¶
JavaScript:
async function requestReview(pageUrl, responsibles, message) {
const response = await fetch(`${pageUrl}/@task-review`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({
responsible: responsibles,
text: message
})
});
if (!response.ok) {
throw new Error(`Review request failed: ${response.status}`);
}
return response.json();
}
// Usage
const task = await requestReview(
'http://localhost:8080/Plone/topics/my-page',
['user:editor1', 'group:editors'],
'<p>Please review.</p>'
);
console.log(task['@id']);
Python:
import requests
response = requests.post(
'http://localhost:8080/Plone/topics/my-page/@task-review',
auth=('initiator', 'password'),
headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
},
json={
'responsible': ['user:editor1'],
'text': '<p>Please review.</p>',
},
)
response.raise_for_status()
print(response.json()['@id'])
The responsible values use the standard Plone principal token format:
user:<userid> for a single user and group:<groupid> for a group.
Working with Tasks Directly¶
Tasks are normal content objects, so they can be listed, read, and transitioned
through the regular plone.restapi endpoints. List the tasks in a user’s
container with a GET on the container, read a single task with a GET on it,
and move it through the workflow with the standard @workflow transition
endpoints using the transition ids from the table above.
POST /Plone/Members/editor1/tasks/my-task/@workflow/task_workflow--TRANSITION--erledigen--offen_erledigt HTTP/1.1
Host: localhost:8080
Accept: application/json