Skip to content

Views and dashboards

The optional Orchestra Views submodule (orchestra_views) exposes the engine's runtime entities to Views, so you can build dashboards over your processes without writing code. Enable it and the Orchestra content entities become Views base tables, complete with relationships, readable labels and a tenant-aware filter; it also ships ready-made dashboards you can use as-is or clone, grouped under a Views item in the Orchestra admin menu.

The views over work items live in a second submodule, Orchestra Inbox Views (orchestra_inbox_views), which depends on both orchestra_views and orchestra_inbox. They need each side: the work item comes from the inbox, the Views integration from here. Neither parent can ship them alone, so enable that module for the task lists.

What it exposes

Installing the module attaches a Views data handler to each Orchestra content entity, turning every base field into a field/filter/sort and every reference into a relationship:

Base table Entity Key relationships
orchestra_instance Process instance parent token
orchestra_token Token (a branch in flight) instance, parent token
orchestra_variable Process variable instance, token
orchestra_work_item User task (needs orchestra_inbox) instance, token, assignee, completer
orchestra_incident Incident (a dead-lettered branch) instance, token, resolved by

Workflows, tenants and the other configuration live as config entities, which Views cannot use as base tables; the dashboards reach them through the readable fields below instead.

Readable labels

The runtime stores machine names for speed: an instance keeps its workflow's machine name, a token keeps a node ID local to that workflow. Two extra fields resolve those to the human labels a dashboard wants:

  • Workflow (on the instance): resolves the stored machine name to the workflow's label. The raw value is still available as Workflow (machine name).
  • Name (on the instance): the label the instance was given when it started or since, for example "Leave request from Jean Dupont", else its workflow's label. Its Show the instance id after the name setting is Never for a list with an id column of its own (Reference, ID), Only for an instance given no label ("Leave request #15", the default), or Always ("Leave request from Jean Dupont #15"). The given label alone is also available as Label, to sort or filter on.
  • Node label (on the token): resolves the token's node ID against its instance's workflow definition.
  • Current step (on the instance): where a running instance is waiting now, its parked non-timer tokens mapped to their version-pinned node labels (joined when a run is on several branches at once). Backed by the reusable orchestra_engine.current_step_resolver service, so a page and a View report the same step.
  • State (on the instance): the engine lifecycle, rendered as its human label (Running, Completed, Canceled, Failed) rather than the raw machine value.
  • State (on the token): where a branch stands, rendered as its human label (Active, Parked, Waiting at a join, Consumed, Canceled, Error) rather than the raw machine value. The Instance and Tokens views below show it. An option renders it on the shared status tag, colored by state: active in blue, parked and waiting in amber, consumed in green, canceled in red, and an error in the strong red of a failed instance.
  • Status (on the instance): the workflow-authored status the current node references, rendered as its vocabulary term label (for example "Under review" or "Approved"), empty when the workflow authors none. An option renders it as a styled tag carrying the author's CSS classes, so a theme can color it.

There is also a Workflow filter on the instance that offers the workflows by label as a select/checkbox list, so you can scope a dashboard to one or more workflows without typing machine names. Like the Status filter, it lists only the workflows available in the acting tenant, because a workflow's label is authored text and another tenant's names are not this operator's to read; uncheck Limit to the current tenant for a cross-tenant dashboard. The workflows are listed in the order arranged on the Workflows list (weight, then label, so plain label order on a site that never arranges them); set Order of the workflows to By label for a site with too many workflows to arrange. It leaves out the workflows marked Runs only as a subprocess while Exclude subprocess-only workflows is on, its default. The same filter exists on the instance's Top-level workflow, which names the workflow of the top-level instance a subprocess child belongs to, so a list can find a child under its request (see subprocesses).

State versus Status

An instance carries two distinct values, each with a labeled field and a labeled filter:

  • State is the engine lifecycle (running, completed, canceled, failed), set by the engine. Its filter offers the four states as a labeled select.
  • Status is the workflow-authored value the current node references, a tenant-scoped status vocabulary term that speaks to the business. Its filter lists the vocabulary terms as a labeled select, limited to the current tenant by default (a setting toggles this to list every tenant's terms).

Both filter on the stored machine value, so they stay one query; only the field and filter labels are resolved for display.

Process variables as columns and filters

A process carries named variables (see Concepts), and the instance offers a Process variable field that shows one of them as a column. Add the field, name the variable, and choose how to display it:

  • Variable: the variable to show. A dotted name reads the way flow conditions read it: the variable of exactly that name when there is one (submission.city, a webform answer stored on its own), else into a structured value: order.total shows the total key of the array held in order. A plain name shows a scalar.
  • Display as: Text, Number, Date (a Unix timestamp or a date string, formatted with the chosen date format), Yes/No for a boolean, or User for a variable naming a user by user ID, username or email address, as the Users by variable audience reads it: the account's display name, linked to it when Link to the user is checked and the viewer may see profiles. A blocked account still shows, unlinked unless the viewer administers users. The accounts are loaded once for the page.

The field reads the instance-wide value, not a branch's token-local one, and the named variable is loaded once for the whole page, so a column over many instances stays one query. Add the field more than once to show several variables side by side.

The instance also offers a Process variable filter, to list only the instances whose variable holds a given value. Name the variable, pick an operator, and type the value, or expose the filter for the person reading the list to choose:

  • Is / Is not: the value, whether it was stored as text or as a number (42 finds both), or true, false. Is not also lists the instances that never set the variable.
  • Contains / Starts with: text, including inside a list (hr finds ["hr", "legal"]).
  • Is less than, greater than, or equal: numbers only; a variable holding text never matches.
  • Is empty / Is not empty: no value, an empty text, list or map, or never set.
  • Is the current user: for a variable naming a user, the person viewing the list, so one view lists "the requests I manage" for everyone. It matches the viewer's user ID, username or email address, whichever the variable holds, by the same rule as the Users by variable audience. The list then varies by user; an anonymous viewer matches nothing.

For a variable naming a user, check Choose the value as a user to pick the value of Is and Is not by name through an autocomplete, exposed or not, instead of typing it. It matches the chosen user's ID, username or email address.

Text is compared as the database compares it: on MySQL case does not matter (HR finds hr), on SQLite and PostgreSQL it does for Is.

A dotted name matches the variable of exactly that name, such as a webform answer stored on its own (submission.department); filtering inside a structured value is not supported, since the database would have to read inside every stored value. Like the field, it reads the instance-wide value, not a token-local one. Each filter adds one indexed lookup per instance to the query, and an index on the variable's name and value serves Is and Starts with on a large table.

Tenant scoping

Every Orchestra entity carries a tenant (see Multi-tenancy). The module adds a Current tenant filter to all five entities: enabled, a view shows only the rows of the tenant the request is acting in. The shipped dashboards all carry this filter, so on a multi-tenant site each operator sees only their own tenant's work; on a single-tenant site every row is the default tenant, so the filter simply narrows to everything.

The orchestra_tenant cache context

The filter resolves the active tenant through the same tagged resolvers the engine uses, and declares the orchestra_tenant cache context so cached output never leaks across tenants. That cache context ships in the base module and is reusable by any tenant-scoped render (a block, a custom dashboard).

The shipped views

Enabling the modules installs these views. They are ordinary views: clone or edit them freely. Every one lives under a views/ path, beside the native page of the same name when Orchestra has one, so a path says which kind of page it is: /admin/orchestra/instances is the operator page orchestra_ui builds, /admin/orchestra/views/instances the view a site can rebuild to its taste.

View (id) Path Native counterpart Module Permission
Instances (orchestra_instances) /admin/orchestra/views/instances /admin/orchestra/instances orchestra_views Administer Orchestra
Instance (orchestra_instance) /admin/orchestra/views/instances/{id} /admin/orchestra/instances/{id} orchestra_views Administer Orchestra
Tokens (orchestra_tokens) /admin/orchestra/views/tokens none orchestra_views Administer Orchestra
Tasks (orchestra_tasks) /admin/orchestra/views/tasks none orchestra_inbox_views Reassign Orchestra tasks
Inbox, Inbox history (orchestra_inbox) /orchestra/views/inbox, /orchestra/views/inbox/history /orchestra/inbox orchestra_inbox_views Process Orchestra tasks
My requests (orchestra_requests) /orchestra/views/requests /orchestra/requests orchestra_views View own Orchestra process instances

All of them are confined to the current tenant for anyone without Administer Orchestra, whatever their filters (see Tenant scoping). The current-tenant filter additionally narrows an administrator's view on every one except Tasks, which shows an administrator every tenant's tasks.

Instances

Every process instance of the current tenant, running or finished, newest first, 50 a page. Columns: ID, Name (the instance's label, else its workflow's), State (Running, Completed, Canceled, Failed), Status (the author-defined status, see State versus Status), Started, Last updated, and Trace, a link to the instance's own page, shown only to a reader who may open it. The State filter is exposed and empty by default: leave it for every instance, pick Running for the work in flight, or a finished state for reporting. It replaces the earlier pair of running-only and finished-only dashboards.

Instance

One instance's node-by-node trail: every token it produced, consumed ones included, in the order they arrived, 100 a page. The instance ID is the last path segment, and the title reads "Instance {id}". Columns: ID, Node, State, Arrived via (the flow; "Join fired" for the token a join created when it fired, which keeps the flow of the arrival that fired it), From token (the branch it belongs to), Arrived and Updated. It has no menu entry: the Instances lists link to it per row. On a site with orchestra_ui, rows link to the fuller native instance page instead; this view is the trail for a site running Views alone. See Process history and trace.

Tokens

The live tokens of the current tenant (neither consumed nor canceled), the engine's in-flight branches, newest first, 50 a page. Columns: ID, Process, Node (the label), State and Created on. A diagnostic list: a token that sits on one node far longer than its siblings is where a process is stuck.

Tasks

Every open user task (open, claimed or in progress; pull-mode operations left out), newest first, 50 a page, for the managers who answer for stuck work. Columns: ID, Task, Process, Assignee (or the pool it is offered to), State, Created on, Tenant and Operations. Operations offers what the reader may do: on a task nobody holds, claim, open and the one-click outcomes; on a task somebody else holds, only Reassign and Return to pool for a manager, since a held task is worked by its holder alone, and those plus open and the outcomes for an administrator, who may work any task of the current tenant (see Reassignment). It has no current-tenant filter: an administrator sees every tenant's tasks, and the Tenant column says whose each one is; a manager without Administer Orchestra sees their tenant's. Listed in the Orchestra admin menu and under Structure > Orchestra.

Inbox and Inbox history

The acting user's own tasks, as two tabs of one view rendering the same card row: Inbox (what they may act on now) and Inbox history (what they have processed). Each card is headed by the instance's name (its label, else its workflow), and shows the task state, the initiator, the reference, when it was created, the status, the process state, the step it is waiting on, who holds it, and its operations. Both tabs expose Application, Workflow and Status filters, 10 cards a page; the Workflow filter matches a task by its request's top-level workflow, so a subprocess child's tasks are found under the request's workflow. The native inbox at /orchestra/inbox is the same list as a table. See Inbox.

My requests

The top-level instances the acting user started, not the subprocess children they started in turn, for a requester who holds no administrative permission: reference, name (the instance's label, else its workflow), state, status, the step it is waiting on and when it was created, with a link to each request's page, 25 a page. Workflow, State and Status filters are exposed. The native page at /orchestra/requests is its themed counterpart. See My requests.

Every one of them is reachable from Views in the Orchestra admin menu, next to Tenants and Settings. Each link is declared by the module that guarantees its route exists, which is why the Tasks and Inbox views come from orchestra_inbox_views: a link declared by either parent alone would point at a route that was never registered on a site running only that parent. The trace view gets no link, since it takes an instance ID and has no argument-less landing page; the dashboards link to it per row instead.

Process history and trace

A finished process keeps its whole execution: every node it passed through is a retained token (the engine consumes a token rather than deleting it, and spawns the next one on the outgoing flow), so the token table already holds the trail. Two views surface it:

  • Instances, filtered on a finished state, lists finished instances with their started (created) and last updated (changed) times.
  • Instance takes an instance ID in its path and lists all that instance's tokens (consumed ones included) in chronological order, showing the node, state, the flow each arrived on and its parent token (the branch it belongs to). The Instances list carries a Trace link per row that opens it.

This is a per-node-occupancy trail: each token records when it arrived and its final state, which reconstructs which nodes ran, in what order, on which branch and ending how. It is not a full per-transition event log: a token keeps only its last changed time, and variable changes are not retained. For a durable, append-only record that survives instance deletion, enable the optional Audit log submodule.

My requests (requester-facing)

The dashboards above are operator surfaces gated by administrative permissions. For the person who started an instance, orchestra_views ships a My requests view at /orchestra/views/requests: it lists only the instances the current user initiated (the Initiated by the current user filter over the initiator), scoped to the acting tenant, showing each request's reference, workflow, state, status and Current step, with exposed State and Status filters. It is gated by a dedicated View own Orchestra process instances permission, so a requester needs no operator rights. orchestra_ui offers the same list as a themed card page at /orchestra/requests under the same permission; the two are interchangeable, so keep whichever fits the site and remove the other.

For them to read the same the Views one renders the same parts: its rows are the shared card row, the same one the card page renders, its Reference is the run's correlation key falling back to the run's id (linked to the run, as on the card page), its Status is the authored status on the shared tag with the engine state beneath it as the lifecycle marker, and its Current step is hidden on a row that has none rather than left as an empty column.

It also carries an Action link, the row's call to action: the step of that run which is waiting on the viewer, opened where its family says it is acted on. Both this and the themed page ask one service, orchestra_engine.pending_actions, so neither can offer a step the other does not. A run waiting on somebody else, or on nothing, shows no link, which is what makes the column safe in a list an operator can also open.

Giving one step its own look

Every control offered for a step carries CSS classes naming that step, so a design can put its own icon on one step and something else on another without replacing a template. Two modifiers ride on a base class, both built from machine names run through Html::getClass():

Control Classes
The action link (this view, the task lists, the themed card page) orchestra-action, orchestra-action--{node}, orchestra-action--{workflow}-{node}
The operations widget (the task lists and the inbox page) orchestra-operations, orchestra-operations--{node}, orchestra-operations--{workflow}-{node}

{node} is the step's machine name inside its workflow definition, and {workflow} the workflow's own. So node n_review of workflow change_of_address yields orchestra-action--n-review and orchestra-action--change-of-address-n-review.

Prefer the workflow-scoped modifier

A node id is local to its workflow, so unrelated workflows routinely reuse the same one: a site with a handful of workflows will have n_start and n_end in most of them, and a convention like n_review in several. A rule written against orchestra-action--n-review therefore fires on every workflow using that id. Style orchestra-action--{workflow}-{node} unless you genuinely mean "this step wherever it appears".

All four surfaces emit the same hook, so a step styled once is styled everywhere it is offered.

An icon still needs a name

Styling the control down to a glyph removes the only thing that tells a screen-reader user which step it opens, and a list of identical unnamed controls is worse than no icon. Keep the action label in the markup and hide it visually (core's visually-hidden), rather than replacing the text with the icon or relying on title.

Current step and Action link are not the same string

The column resolves the run's parked tokens against the version its run pinned; the link is labeled with the step's action label, read live. They read alike by default, since both are the node's label, and diverge exactly where that matters: a node with its own action_label, or one renamed after the run started.

Linking to a run, without typing a path

Three shipped fields open one of a run's pages, and all build the link from the route rather than from a path written into the view:

Field Opens Shown when
Name (Link to the instance on) The instance's read-only page, from its name The viewer may read the instance; anyone else reads the name as plain text
Reference (Link to the instance on) The instance's read-only page The viewer may read the instance
Trace link The fullest trace the site has: the instance page when orchestra_ui is installed, else the Instance view here The viewer may open that page

Use Name rather than core's entity reference label on a task's or a token's instance: that formatter asks the instance entity whether its label may be seen, and the instance entity answers no to everyone, so the column renders empty.

A path in a view's configuration cannot ask whether the viewer may follow it, and it rots the day a route moves: every site that installed the view keeps the old path until the view is re-imported. A field with a route name has neither problem, so prefer these over a custom-text field with a hand-typed path in your own views too.

The Trace link's preference matters on a site without orchestra_ui: this module does not depend on it, so the Instance view is then the only per-instance trail, and the column opens that. Install the UI and the same column opens its instance page instead, which shows the same trail plus the run's summary, variables, incidents and operations, and which a tenant-scoped operator may open while the trace view is administrator-only.

Inbox (operator-facing)

orchestra_inbox_views ships an Inbox view (orchestra_inbox) with two page displays, sibling tabs over the same rows:

  • Inbox at /orchestra/views/inbox: what the acting user may act on now, via the Actionable by the current user filter.
  • Inbox history at /orchestra/views/inbox/history: what that user has already processed, via the Completed by the current user filter.

The Actionable by the current user filter reads through any standing delegation, so a stand-in's list includes the work they cover, pooled and already-claimed alike. The history filter does not: it is keyed on the completer, which is always whoever actually acted, so covering for somebody never rewrites their record or borrows it.

Cover and cached lists

Cover is granted, withdrawn, and dated, and none of that touches a single task row, so a page cached on the rows alone would go on showing a stand-in the list they had before. The filter declares what it read: a cached list carries the orchestra_delegation_list tag and expires at the next moment any cover it consulted starts or ends, so it is right from the minute the cover is.

A third personal filter, Handled on the current user's behalf, reads the same rows from the delegator's side: what somebody did in your name while you were away. The shipped View carries no display for it, since a tab for an optional submodule's field would sit empty on every site that never delegates; adding it to a duplicate of the history display is a two-click job. The three are not interchangeable, because each asks about a different person:

Filter Answers Keyed on
Actionable by the current user May I act on this? assignee + candidates, read through cover
Completed by the current user Did I process this? completer
Handled on the current user's behalf Was this mine, done by somebody else? on_behalf_of

One completed delegated task legitimately answers the last two at once: it is in the stand-in's history because they acted, and in the delegator's on-behalf list because it was their work.

The three user-shaped columns on a work item (assignee, completer and on behalf of) are stored as plain user ids, so that the work-item table carries no hard dependency on the user entity type. Views therefore exposes them as numeric columns rather than as relationships to the user entity: each gets a filter-by-username, and the readable Held by field renders the display name (with "(for somebody)" appended when a delegation is what brought the work within reach).

On both tabs the Reference column links to the instance behind the task, its read-only page: holding the task, or having completed it, is what entitles the viewer to read the instance (see read access), so no operator permission is involved. The column is a field with a Link to the instance checkbox, not a path typed into the view: the field builds the link from the route, offers it only to a viewer the page admits (plain text for anyone else, never a link to a 403), and carries the list it was clicked on as the return target, so the instance's page leads back to that tab with its filters and pager.

They are two displays of one view rather than two views, so both tabs share one row template and cannot drift apart. The module ships that template, and it needs no theme work: each row renders as a card on the shared orchestra_presentation/cards component, the same one the requester's list of runs uses. To restyle just these tabs, override views-view-fields--orchestra-inbox.html.twig in your theme and both follow; to restyle every personal list at once, the Views ones and the card page at /orchestra/requests, override orchestra-card-row.html.twig instead.

That template prints one thing, the shared card row orchestra_card_row in orchestra_presentation, which every shipped personal list renders. The requester's My requests page at /orchestra/requests is a controller rather than a view, and hands the row the same parts, so overriding the row template reaches it too.

To lay out only some cards, name the copy of orchestra-card-row.html.twig after a suggestion. A card says the kind of list it is in, request or task, and the tenant, application and workflow of its instance. For a task of the workflow leave_request, in the application hr and the tenant north, Drupal tries these, the first one found wins:

  1. orchestra-card-row--task--north--leave-request.html.twig
  2. orchestra-card-row--task--north--hr.html.twig
  3. orchestra-card-row--task--north.html.twig
  4. orchestra-card-row--task--leave-request.html.twig
  5. orchestra-card-row--task--hr.html.twig
  6. orchestra-card-row--task.html.twig
  7. orchestra-card-row.html.twig

A request card tries the same names with request in place of task. An id's underscores are written as hyphens, and a workflow in no application has no application suggestion. Tenant, application and workflow ids share one name space: give them distinct machine names, or a template named after one also reaches the other.

For example, to put the call to action first on every task card of the hr application, and leave every other card as shipped:

{# orchestra-card-row--task--hr.html.twig #}
{{ attach_library('orchestra_presentation/cards') }}
<div class="orchestra-card">
  {% for action in calls_to_action %}
    <div class="orchestra-card__action">{{ action }}</div>
  {% endfor %}
  <h2 class="orchestra-card__title">{{ heading }}</h2>
  {{ badge }}
  {% for column in columns %}
    {{ column }}
  {% endfor %}
</div>

The card also gets kind, tenant, application and workflow, so one template can still tell its cards apart, for example {% if workflow == 'leave_request' %}.

Which field plays which part is said in the row's preprocess, so your own list matches the shipped ones by building the same card:

#[Hook('preprocess_views_view_fields__my_list')]
public function preprocessMyListRow(array &$variables): void {
  $variables['card'] = [
    '#theme' => 'orchestra_card_row',
    '#fields' => $variables['fields'],
    '#title' => 'label',
    '#tag' => 'task_state',
    '#status' => 'status',
    '#lifecycle' => 'state',
    '#actions' => ['action_link', 'operations'],
  ];
}

Add #kind, #tenant, #application and #workflow to the card for its template suggestions, as the shipped rows do; a card given no kind gets none.

with views-view-fields--my-list.html.twig being just {{ card }}. A theme can do the same in its .theme file, for a view it did not build.

The title field is the card's heading, tag renders its own status tag beside it, status and lifecycle pair into one column (the authored status, with the engine state beneath it as the always-present marker), and actions sit at the end of the row, the first of them styled as the card's call to action. Every field not named becomes a labeled column, in the order the view lists them, so cloning the view and adding a field lays that field out for you.

The card's own components

The row is built from three components orchestra_presentation owns, each a theme hook a theme overrides once for every Orchestra surface (the personal lists, a run's own page, the task inbox, and any view of your own):

Theme hook Variables What it renders
orchestra_status_tag label, classes The prominent pill: an authored status, a task's state, or an engine state where that is all there is to show.
orchestra_lifecycle_marker label, classes The engine state as a small muted marker with a state-colored dot.
orchestra_card_column label, value, classes A labeled column. value is one value or a list of parts, shown in the order given.

The tone is always in classes, passed by the caller: a status takes its palette from its vocabulary term, a task state and an engine state from their own per-state convention, so a workflow introduces a tone by naming a class your theme styles, with no code change. The tag and the marker are separate hooks and a column shows whatever parts it is given, so a surface of your own can show an authored status without an engine state, or the other way round.

Each row carries the task's label, its own state, who holds it, the business data from its process (through the instance relationship: the initiator, the correlation key, the workflow status as its term label, the engine state and the Current step) and its Operations. The history display swaps the operations for the outcome and the processed time.

These handlers make this work, all of them usable in your own views:

Handler Type What it does
Actionable by the current user filter The visibility rule the inbox applies: assigned to the acting user, or unassigned and pooled either to everyone or to one of their audiences.
Completed by the current user filter The items the acting user completed, read from the completer recorded at completion.
Operations field Every action the task offers the viewer, as the inbox offers them: claim it, open it, each outcome that needs no opening in one click, reassign it, return a claimed one to its pool.
Action link field Just the link opening the task where its family declares it is acted on, labeled with the task's action label. Operations already leads with this link, so a display carrying operations needs no separate action link.
State field The task's own state as its human label (Open, Claimed, In progress, ...), optionally on the shared status tag. Distinct from the engine state of its process.
Outcome (label) field The outcome the task was completed with, as its authored label, optionally on the shared status tag in the color its step gives the outcome (outcome colors). The history display shows it as a tag.
Held by field The assignee's display name, or who the task is offered to while it is still in a pool: the same wording the inbox uses.
Assignee field The assignee as a linked username, for a viewer who may follow the link; while the task is still in a pool, who it is offered to, in the Held by wording. Use it rather than a "No results text" for the unassigned case: core never translates that text.

Three fields on the instance serve any personal list, not just these: Reference (the correlation key, falling back to the run's id, so the column always names the run), Status with its Render as a styled tag option (the tone comes from the status vocabulary term, so a workflow colors its own steps), and State with its Render as a lifecycle marker option (a muted label with a state-colored dot, since the engine state has no term behind it to take a palette from).

Operations and the action link both ask the task's family where it is acted on, and they ask it through the family's pending-action handler, which is the seam every task type declares that surface through. A family shipping its own handler, an interaction task for instance, is therefore opened from a view exactly as it is opened from the inbox page. Both also thread the listing's own URL on as the return target, so acting on a task from a view comes back to that view, on the page and in the sort order you left it.

The two filters are not interchangeable. The first answers may I act on this, the second did I process this. Neither says anything about state, so pair them with a state filter: the shipped displays exclude completed and canceled items from the first tab and keep only completed ones in the second.

An item completed with nobody identifiable acting, such as an external interaction resumed through a bearer link or an engine-driven timeout, records no completer and so appears in no personal history. That is deliberate: there is no user whose history it belongs in. Operations and the action link are likewise empty for a finished task and for a row the viewer may not act on, so both columns are safe in a list a manager can also open.

Carrying the operations column is what makes these lists usable instead of the inbox at /orchestra/inbox rather than only alongside it: the same actions, built by the same code, on a surface you can filter, sort and theme. Keep whichever fits the site.

Building your own

Add a view on any of the five base tables and you have the fields, filters and relationships above to work with. A few patterns:

  • Per-workflow board: add the Workflow filter (exposed) and group by it.
  • Stuck work: on tokens, filter state = parked and sort by deadline.
  • Variables of a process: start from orchestra_variable, add the instance relationship, expose an instance ID argument.
  • A team's queue: on work items, start from the shipped My tasks view and swap Actionable by the current user for a plain assignee or candidates filter.
  • Open incidents across tenants: on incidents, filter state = open and drop the Current tenant filter.

Bulk actions

To act on rows from a dashboard, enable the Orchestra VBO (orchestra_vbo) submodule and add a Views bulk operations field to a view. It ships Views Bulk Operations actions over the same entities:

Submodule Entity Actions Permission
orchestra_vbo Process instance Cancel process, Delete process Administer Orchestra
orchestra_vbo Token Resume (signal) token, Cancel token Administer Orchestra
orchestra_vbo_inbox Work item (task) Claim (assign to me), Complete task, Reassign task Process / Reassign Orchestra tasks

Every one of them is reached through the Views bulk operations field: core's own Bulk update field lists action config entities rather than action plugins, and the project ships none. The task-inbox actions (orchestra_vbo_inbox) need orchestra_inbox; Complete task takes an optional outcome to record on each task, and Reassign task a target user. Each action is gated on the matching permission.

Delete process additionally refuses a running instance, the same rule the instance page and its delete form apply: cancel the run first, then delete it. A refused row is listed with that reason and the rest of the selection is still processed, so a mixed selection deletes what it may. To clear running rows, run Cancel process over them first and Delete process after.