Volto add-on#
The frontend package is @plone-collective/volto-multiworkflow.
It renders the additional workflows of the current content object, and renders nothing at all on content that has none.
Every payload shape named here is described in REST API.
Customizations#
The add-on shadows two core components.
volto/components/manage/Workflow/WorkflowPuts each additional workflow's state and transitions in the same control as the publication workflow, rather than in a separate menu.
volto/components/manage/History/HistoryRenders the merged history, naming the workflow of each entry when the history spans more than one.
Neither shadow changes what the component renders for content without additional workflows.
Components#
AdditionalWorkflowRenders one additional workflow: its title, its current state, and the transitions available to the user. The title is the label declared for the workflow on the backend, when there is one.
AdditionalWorkflowMenuRenders the transitions of one additional workflow as a menu.
StateBadgeA compact label for one workflow's current state, for use in listings. It renders from either shape the backend serves, and takes an optional
classNamewith both. Given anentry, one chain entry of the@workflowpayload, it shows the translated state title, with the workflow's title in thetitleattribute. Given avalue, oneworkflow_statesvalue of a content object or a catalog summary, it shows the optional translatedlabel, or the state id when there is none. A value with no separator renders nothing. A listing can usevaluewith no@workflowrequest per item. Either way it emitsdata-workflowanddata-stateattributes carrying the stable ids, which is what styling and acceptance tests should key on rather than the translated titles.
Helpers#
getPrimaryWorkflow(chain?)The first chain entry, the one driving
review_state.undefinedwhen the chain is empty or absent.getAdditionalWorkflows(chain?)Every entry after the first—the additional workflows. Empty for content that does not use this add-on.
hasAdditionalWorkflows(chain?)Whether there is any additional workflow worth rendering.
threadPreviousStates(entries)Fills in each history entry's
prev_state_title, per workflow. A merged history breaks the assumption that entry N-1 is the previous state of entry N, because the preceding entry usually belongs to a different workflow. Entries are taken and returned newest first.markCurrentVersion(entries)Sets
is_currenton the newest versioning entry.spansMultipleWorkflows(entries)Whether a history mixes entries from more than one workflow. The History view uses this to decide whether naming the workflow is worth a column.
getWorkflowTitles(chain?)Maps every workflow id in a chain to its translated title, which is the label declared for the workflow when there is one. History entries carry only
workflow_id, so a view that labels them reads the chain as well.getWorkflowStates(item?)The
workflow_statesvalues of a content object or a catalog summary, in chain order. Empty when the item carries no such key.getAdditionalWorkflowStates(item?)Every
workflow_statesvalue after the first—the states of the additional workflows.parseWorkflowState(value)Splits a
workflow_statesvalue intoworkflow_idandstate_id.undefinedfor a value with no separator.formatWorkflowState(workflowId, stateId)Builds a
workflow_statesvalue out of the two ids.
Constants#
WORKFLOW_STATE_SEPARATORThe
|separating the workflow id from the state id within aworkflow_statesvalue.WORKFLOW_STATES_VOCABULARYThe name of the backend vocabulary holding one term per state of every workflow. Its tokens are
workflow_statesvalues, and its titles read<workflow>: <state>, naming the workflow by any label declared for it. Anyone who can view the context can read it, so it is where a listing takes thelabelof a value from.
Actions#
getMultiWorkflow(url)Fetches the full
@workflowpayload, includingchain.transitionMultiWorkflow(transitionUrl)Executes a transition by posting to the
@idreported for it.
Important
Both actions exist because core's workflow reducer keeps only state, history, and transitions from the @workflow response, so chain never reaches the store.
A transition's response is the last review_history entry, not a workflow payload, so the chain must be re-fetched after a successful transition.
Store#
The add-on installs one reducer under multiworkflow.
Key |
Type |
Meaning |
|---|---|---|
|
|
a request is in flight |
|
|
the last request succeeded |
|
|
the last failure, if any |
|
|
the current object's chain; empty when it has none |
Content without additional workflows reduces to an empty chain, so a consumer can render nothing without special-casing the absent key.
Types#
WorkflowState, WorkflowTransition, WorkflowChainEntry, WorkflowInfo, HistoryEntry, MultiWorkflowState, WorkflowStateValue, ParsedWorkflowState, and WithWorkflowStates are exported from the package root.
They mirror the backend serializer exactly and are the single source of truth for consumers. They must be updated in the same commit as any serializer change.