Task Page
A task page is the form of one user task of your process, e.g. an approval. It opens in a new browser tab when a user works on a task from the task list.
File: src/apps/{processId}/tasks/{taskfolder}/{TaskPage}.tsx - opened at /task/{taskId}.
Finding the file name
The name comes from the task name in the BPMN model:
folder | remove spaces, all lower case |
|
file | capitalize the first letter of every word, remove spaces |
|
src/apps/purchase/tasks/approverequestlevel1/ApproveRequestLevel1.tsx
Easiest way: open the task once without a page. The generic task page shows the exact path it expects, plus the complete task data as JSON.
Add ?edit to the task URL (/task/{taskId}?edit) to see the generic JSON view even when your page exists - handy to check the raw data.
Example: approval task
import { useAuth } from "@/ecc/auth/AuthProvider";
import { useHideSideNav } from "@/ecc/context/LayoutContext";
import { EccPageWrapper } from "@/ecc/core/EccPageWrapper";
import { EccText } from "@/ecc/components/forms/EccText";
import { EccDate } from "@/ecc/components/forms/EccDate";
import { EccBoolean } from "@/ecc/components/forms/EccBoolean";
import { EccTextarea } from "@/ecc/components/forms/EccTextarea";
import { EccPanel } from "@/ecc/components/forms/EccPanel";
import EccProcessHistory from "@/ecc/components/widgets/EccProcessHistory";
import { PurchaseTaskValidator } from "@/apps/purchase/tasks/PurchaseTaskValidator";
import type { EccTask } from "@/ecc/types/taskTypes";
export default function ApproveRequestLevel1({ task }: { task: EccTask }) {
useHideSideNav();
const { user } = useAuth();
return (
<EccPageWrapper validatorClass={PurchaseTaskValidator}>
<div className="ecc-page">
<div className="container-fluid">
<h1>{task.name}</h1>
<div className="infotext-page">{task.description}</div>
</div>
<div className="row g-4 mt-2">
<div className="col-12 col-md-8">
<EccPanel title="Request">
<EccText fieldLabel="Title" value="inputs.purchase.title" data={task} />
<EccText fieldLabel="Type" value="inputs.purchase.requestType" data={task} />
<EccText fieldLabel="Reason" value="inputs.purchase.reason" data={task} />
<EccText fieldLabel="Requester" value="inputs.purchase.requester.email" data={task} iconPreset="mail" showIcon copyable />
</EccPanel>
</div>
<div className="col-12 col-md-4">
<EccPanel title="Decision">
{/* written into the output, not visible */}
<EccDate valueOut="output.decisionBoolean.decisionDate" initValue="now" hidden />
<EccText valueOut="output.decisionBoolean.decisionMaker.name" valueInit={user?.name ?? ""} hidden />
<EccText valueOut="output.decisionBoolean.decisionMaker.email" valueInit={user?.email ?? ""} hidden />
<EccText valueOut="output.decisionBoolean.decisionId" valueInit="purchase.approval01" hidden />
<EccBoolean fieldLabel="Approve request?" valueOut="output.decisionBoolean.approved"
initValue={false} checkStyle="toggle" editable
trueLabel="Approve" falseLabel="Reject" />
<EccTextarea id="decisionComment" fieldLabel="Comment" valueOut="output.decisionBoolean.comment"
rows={6} editable />
</EccPanel>
<EccProcessHistory processInstanceId={task.rootProcessInstanceId ?? task.processInstanceId} />
</div>
</div>
</div>
</EccPageWrapper>
);
}
Ecc components in this example: EccPanel, EccText, EccDate, EccBoolean, EccTextarea - how to use them is described in UI Components. Page frame: EccPageWrapper. Widgets in this example: EccProcessHistory. Objects in this example: EccTask.
Values that contain a dot and no space - e-mail addresses, ids like purchase.approval01, version numbers - would be read as a path. Pass such fixed or computed values as valueInit, not as value.
Reading task data
The page receives the task as EccTask. The data of the task is in inputs:
| business data mapped into the task, e.g. |
| task metadata from the model |
| task name and description |
| the case the task belongs to |
| who works on it, who may |
Writing the task output
Every field with valueOut="output.<variable>.<field>" contributes to the task output. With the fields above the output is:
{
"output": {
"decisionBoolean": {
"decisionDate": "2026-09-30T08:12:45.118Z",
"decisionMaker": { "name": "Max Keller", "email": "max.keller@example.org" },
"decisionId": "purchase.approval01",
"approved": true,
"comment": "Budget confirmed."
}
}
}
The names below output are the data outputs of the user task in the BPMN model (here decisionBoolean of type EccDecisionBoolean, whose decisionMaker is an EccPerson). Check them in the Schema Explorer for the task node.
During development, drop in EccGenerateJsonOutputButton to copy the current output JSON to the clipboard:
import { EccGenerateJsonOutputButton } from "@/ecc/components/forms/EccGenerateJsonOutputButton";
<EccGenerateJsonOutputButton />
Who may open a task
The platform checks access before your page is shown. A task owned by someone else, or a task the user is excluded from (e.g. the requester of an approval), shows a not found page instead.
On this page
- Task Page