Process Instance Page
The process instance page shows one business case: its data, documents, diagram, open tasks and history.
File: src/apps/{processId}/{ProcessId}Instance.tsx - opened at /process/{processInstanceId}. The URL also accepts the business key, e.g. /process/PR260930-3f9a1c2b.
Without this file the platform shows a generic view of the process, so you only build the page when you want your own layout.
Example
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useHideSideNav } from "@/ecc/context/LayoutContext";
import { usePageTitle } from "@/ecc/core/usePageTitle";
import { EccProcessPageWrapper, useEccProcess } from "@/ecc/core/EccProcessPageWrapper";
import EccPageHeader from "@/ecc/components/widgets/EccPageHeader";
import EccProcessInstance from "@/ecc/components/widgets/EccProcessInstance";
import { ProcessDetail } from "@/ecc/components/widgets/ProcessDetail";
import { EccProcessDiagram } from "@/ecc/components/widgets/EccProcessDiagram";
import { EccText } from "@/ecc/components/forms/EccText";
import { EccTextarea } from "@/ecc/components/forms/EccTextarea";
import type { EccProcess } from "@/ecc/types/taskTypes";
export default function PurchaseInstance({ process }: { process: EccProcess }) {
return (
<EccProcessPageWrapper process={process}>
<PurchaseInstanceContent />
</EccProcessPageWrapper>
);
}
function PurchaseInstanceContent() {
useHideSideNav();
const process = useEccProcess(); // the loaded case, anywhere below the wrapper
const { t } = useTranslation("purchase");
usePageTitle(`${t("app.purchase.process.name")} - ${process.businessKey}`);
const [tab, setTab] = useState<"data" | "diagram">("data");
return (
<div className="ecc-page">
<div className="container-fluid">
<EccPageHeader
headline={t("app.purchase.process.name")}
text={t("app.purchase.process.description")}
dataRight={<EccProcessInstance process={process} />}
/>
<div className="row">
<div className="col-12 col-md-8">
<div className="ecc-tabs">
<button className={"ecc-tab" + (tab === "data" ? " ecc-tab-active" : "")} onClick={() => setTab("data")}>Request</button>
<button className={"ecc-tab" + (tab === "diagram" ? " ecc-tab-active" : "")} onClick={() => setTab("diagram")}>Diagram</button>
</div>
<div className="ecc-tab-content">
{tab === "data" && (
<>
<EccText fieldLabel="Request type" value="variables.purchase.requestType" data={process} />
<EccText fieldLabel="Kind" value="variables.purchase.requestKind" data={process} />
<EccTextarea fieldLabel="Reason" value="variables.purchase.reason" data={process} />
</>
)}
{tab === "diagram" && <EccProcessDiagram process={process} />}
</div>
</div>
<div className="col-12 col-md-4">
<ProcessDetail process={process} /> {/* tasks and history */}
</div>
</div>
</div>
</div>
);
}
Ecc components in this example: EccText, EccTextarea - how to use them is described in UI Components. Widgets in this example: EccPageHeader, EccProcessInstance, EccProcessDiagram, ProcessDetail. Objects in this example: EccProcess.
The process object
The page receives the case as EccProcess. The fields you use most:
| id of the case - the only id you use for a case |
| readable key, e.g. |
| process definition |
|
|
| times |
| business data, e.g. |
| sub-processes |
Paths into the business data start with variables.:
<EccText fieldLabel="Title" value="variables.purchase.title" data={process} />
<EccText fieldLabel="Requester" value="variables.purchase.requester.name" data={process} copyable />
<EccDate fieldLabel="Started" value={process.start} displayRelative />
Ecc components in this example: EccDate - how to use them is described in UI Components.
A path needs at least one dot. For a top-level field such as start or processName, pass the value directly: value={process.start} or value={process.processName}.
Lifecycle hooks
If the page needs to run code when it opens or closes, give the wrapper a validator class:
import { EccProcessPageWrapper, EccProcessValidator } from "@/ecc/core/EccProcessPageWrapper";
class PurchaseInstanceValidator extends EccProcessValidator {
private timer?: number;
override onPageLoad() { this.timer = window.setInterval(() => console.log("still open"), 60_000); }
override onPageDestroy() { window.clearInterval(this.timer); } // runs on navigation and on tab close
}
<EccProcessPageWrapper process={process} validatorClass={PurchaseInstanceValidator}>
Useful widgets
business key (copyable), version, state badge, start and last change | |
tabs Tasks (all user tasks of the case) and History | |
the history timeline alone | |
the BPMN diagram of the case with the path taken |
Each widget has its own page under Widgets.
On this page
- Process Instance Page