Skip to content

About

Minimal "history plugins" for Operaton and Camunda 7 Cockpit

Resources

Stars

85 stars

Watchers

9 watching

Forks

Latest commit

 

History

295 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minimal "history plugins" for Operaton and Camunda 7 Cockpit

CI codecov

Note: Due to Camunda 7 EOL in October 2025, these plugins have been tested to be compatible with Operaton 1.0.0-beta-1 and 2 and the repository has been renamed.

Minimal history plugin in action.

Breaking changes

The plugins

Each plugin is a standalone *.js bundle. Built bundles are committed to the repository, so you can deploy them without running the build.

Cockpit

Bundle Where it appears What it does
dashboard-favourites.js Dashboard section + star button on a process definition Star process definitions and list the starred ones on the dashboard with running instance and incident counts
dashboard-integrations.js Dashboard section Lists external tasks that have an incident or are currently locked, with retry and unlock actions (individual and batch)
definition-historic-activities.js Definition tab Statistics + diagram Historic activity statistics with a filter box, plus a three-state diagram overlay: off, per-activity execution counts, or a heatmap of cumulative time with the totals in the badges. All three follow the tab's filter and describe the same records, and both the table and the toggle button say so when the query hit its result cap
definition-tab-modify.js Definition tab Modify Batch modification, message correlation and signal broadcast across instances of a definition. Every operation has a dry run that shows both the instances it would reach and the exact request it would send
instance-auto-refresh.js Instance diagram Toggle button for periodic auto-refresh of the instance view
instance-action-unlock.js Instance action button Dialog listing the instance's locked external tasks, with batch unlock
instance-historic-activities.js Instance tab Audit Log + diagram Audit log for the instance, activity overlays and executed sequence-flow highlighting. Flows taken more than once are drawn heavier, and hovering one names the exact traversal count
instance-route-history.js Definition tab History, instance diagram toggle, and the route #/history/process-instance/:id Filterable, paginated list of historic instances, and a full history view with BPMN viewer, audit log and variables. The diagram carries its own toggles for the executed path and for a time heatmap of where that one instance spent its time
instance-tab-modify.js Instance tab Modify Modify a single running instance (start/cancel activities, transitions) and correlate a message to it
element-template-icon-renderer.js bpmnJs.additionalModules Renders element-template icons on BPMN activities and events
cockpit-custom-styles.js — Injects src/cockpit-custom-styles.scss; no JavaScript behaviour. Also backfills Bootstrap 3 col-xs-* classes that Operaton omits
robot-module.js bpmnJs.additionalModules Draws a Robot Framework icon on service tasks whose id matches /robot/i

Admin

Bundle Where it appears What it does
admin-route-authorization.js Admin route Authorizations Two-panel authorization browser with create, edit and delete, filtering, and a "check resources" pass that flags authorizations pointing at resources that no longer exist
admin-custom-styles.js — Injects custom stylesheets and Bootstrap regression patches for Admin UI
admin-nologin.js — Hides the signin form (see No-login plugins)

Tasklist

Bundle Where it appears What it does
tasklist-audit-log.js Task detail tab Audit Log Audit log of the process instance the task belongs to
tasklist-custom-styles.js — Injects custom stylesheets and Bootstrap regression patches for Tasklist UI
tasklist-nologin.js — Hides the signin form

Welcome

Bundle Where it appears What it does
welcome-custom-styles.js — Injects custom stylesheets and Bootstrap regression patches for Welcome UI
welcome-nologin.js — Hides the signin form

No-login plugins

cockpit-nologin.js, tasklist-nologin.js, admin-nologin.js and welcome-nologin.js contain no JavaScript behaviour at all — each only injects a stylesheet that hides form[name="signinForm"]. They are for deployments where authentication happens outside the webapp (SSO, a reverse proxy, pre-authentication) and the login form would only confuse users. They do not provide authentication and they do not protect anything: the form is hidden with CSS, nothing more.

The no-login plugins are not part of the default Docker image. To hide the login form for any webapp, deploy the corresponding no-login plugin yourself (for Cockpit, using cockpit-nologin-config.js).

Not included

decisions-dashboard.js is abandoned and is deliberately not referenced by any configuration and not bundled into the Docker image. It was an attempt to put DMN decision evaluation directly into Cockpit; that turned out to be the wrong home for it. Use the datakurre.operaton-dmn-modeler VS Code extension instead, which does the same job next to the DMN file you are editing. The sources and the built bundle are kept only so the code stays buildable.

Try it

With Operaton (build image without needing any context directory):

# Build directly from GitHub without cloning:
curl -fsSL https://raw.githubusercontent.com/datakurre/operaton-cockpit-plugins/main/Dockerfile | docker build --no-cache -t operaton-with-plugins -

# Or build from a local clone without build context:
docker build --no-cache -t operaton-with-plugins - < Dockerfile

# Run the container:
docker run --rm -p 8080:8080 operaton-with-plugins

Access Cockpit at http://localhost:8080/operaton/app/cockpit/ (credentials: demo / demo).

With Camunda Platform 7.14.0 and 7.20.0 or later:

$ git clone https://github.com/datakurre/operaton-cockpit-plugins.git
$ docker run --rm -p 8080:8080 -v $(pwd)/operaton-cockpit-plugins:/camunda/webapps/camunda/app/cockpit/scripts/:ro camunda/camunda-bpm-platform:7.14.0

With Camunda Platform 7.15.0 to 7.19.0:

$ git clone https://github.com/datakurre/operaton-cockpit-plugins.git
$ docker run -d --name mytemp camunda/camunda-bpm-platform:7.15.0
$ docker cp mytemp:/camunda/webapps/camunda/app/cockpit/scripts/camunda-cockpit-ui.js operaton-cockpit-plugins
$ docker rm -vf mytemp
$ docker run --rm -p 8080:8080 -v $(pwd)/operaton-cockpit-plugins:/camunda/webapps/camunda/app/cockpit/scripts/:ro camunda/camunda-bpm-platform:7.15.0

See also the example Dockerfile for Camunda Run 7.15.0.

If you don't immediately see the plugin, try again with your browser's private browsing mode. It is a common issue browser has cached a previous Cockpit plugin configuration without these plugins.

Note: Trying out the plugins with Camunda Platform 7.15.0 Docker image is more complex than with the previous version 7.14.0, because the new location of camunda-cockpit-ui.js prevents simple override of the scripts folder.

Use it

Docker (Operaton)

A multi-stage Dockerfile is provided to build a ready-to-run Operaton image with all plugins for Cockpit, Admin, and Tasklist bundled into the internal webapp archives.

Because all assets are fetched during the build stage, no local context directory is required.

Build directly from GitHub:

curl -fsSL https://raw.githubusercontent.com/datakurre/operaton-cockpit-plugins/main/Dockerfile | docker build --no-cache -t operaton-with-plugins -

(or docker build --no-cache -t operaton-with-plugins https://raw.githubusercontent.com/datakurre/operaton-cockpit-plugins/main/Dockerfile)

Use --no-cache when rebuilding from main: the Dockerfile fetches the plugin archive during the build, and Docker cannot detect changes to that remote archive when reusing the fetch layer.

Build from local file without context:

docker build --no-cache -t operaton-with-plugins - < Dockerfile

Customizing build arguments:

docker build \
  --no-cache \
  --build-arg OPERATON_IMAGE=operaton/operaton:latest \
  --build-arg PLUGINS_REF=main \
  -t operaton-with-plugins - < Dockerfile

Run:

docker run --rm -p 8080:8080 operaton-with-plugins

The image covers Cockpit, Admin, Tasklist and Welcome. It does not include the no-login plugins; add those yourself if you need them.

Spring Boot

Each webapp reads its own config.js from its own scripts directory, so the per-app configuration files in this repository have to be renamed to config.js when you copy them. Copy each bundle next to the config that references it:

src/main/resources/
└── META-INF
    └── resources
        └── webjars
            └── operaton
                └── app
                    ├── cockpit
                    │   └── scripts
                    │       ├── config.js                          # from config.js
                    │       ├── cockpit-custom-styles.js
                    │       ├── dashboard-favourites.js
                    │       ├── dashboard-integrations.js
                    │       ├── definition-historic-activities.js
                    │       ├── definition-tab-modify.js
                    │       ├── instance-action-unlock.js
                    │       ├── instance-auto-refresh.js
                    │       ├── instance-historic-activities.js
                    │       ├── instance-route-history.js
                    │       ├── instance-tab-modify.js
                    │       ├── element-template-icon-renderer.js
                    │       └── robot-module.js
                    ├── admin
                    │   └── scripts
                    │       ├── config.js                          # from admin-config.js
                    │       ├── admin-custom-styles.js
                    │       └── admin-route-authorization.js
                    ├── tasklist
                    │   └── scripts
                    │       ├── config.js                          # from tasklist-config.js
                    │       ├── tasklist-audit-log.js
                    │       └── tasklist-custom-styles.js
                    └── welcome
                        └── scripts
                            ├── config.js                          # from welcome-config.js
                            └── welcome-custom-styles.js

After this you can start the project and the plugins should be loaded. Usually you customize config.js per project and define there which plugins are included and where the browser should find them. You may use a browser network inspector to check that Cockpit loads your version of config.js and that the plugin JavaScript files get loaded too.

For use with Camunda 7, use directory ./src/main/resources/META-INF/resources/webjars/camunda/app/... instead.

Other Distributions

Check the forum discussion on how to package plugins for various alternative Camunda distributions.

Configuration

Plugin configuration

Every webapp loads the plugins listed in the customScripts array of its own config.js. This repository ships one configuration file per webapp:

File Webapp Loads
config.js Cockpit the ten Cockpit plugins plus robot-module.js and element-template-icon-renderer.js as bpmnJs.additionalModules entries
admin-config.js Admin admin-route-authorization.js, admin-custom-styles.js
tasklist-config.js Tasklist tasklist-audit-log.js, tasklist-custom-styles.js
welcome-config.js Welcome welcome-custom-styles.js
cockpit-nologin-config.js Cockpit cockpit-nologin.js only — an alternative to config.js

The Cockpit configuration is:

export default {
  customScripts: [
    'scripts/dashboard-favourites.js',
    'scripts/dashboard-integrations.js',
    'scripts/definition-historic-activities.js',
    'scripts/definition-tab-modify.js',
    'scripts/instance-auto-refresh.js',
    'scripts/instance-action-unlock.js',
    'scripts/instance-historic-activities.js',
    'scripts/instance-route-history.js',
    'scripts/instance-tab-modify.js',
    'scripts/cockpit-custom-styles.js'
  ],
  bpmnJs: {
    additionalModules: [
      'scripts/robot-module.js',
      'scripts/element-template-icon-renderer.js'
    ],
  },
  disableWelcomeMessage: true,
  previewHtml: true
};

Drop any line to disable that plugin; the bundles are independent of each other.

localStorage settings

Shared user preferences are stored under the key minimal-history-plugin as a single JSON object:

Setting Type Default Description
autoRefresh boolean false Auto-refresh process instance views
showHistoricBadges boolean false Show activity instance count badges on diagram
showSequenceFlow boolean false Highlight the executed path on the diagram
showHeatmap boolean false Show the time heatmap on a definition diagram (implies showHistoricBadges)
showInstanceHeatmap boolean false Show the time heatmap on a single instance's history diagram
leftPaneSize number null Left pane width in history view (pixels)
topPaneSize number null Top pane height in history view (pixels)
maxResults number 1000 Maximum results for history API queries

Some plugins keep their own state under separate keys:

Key Written by Contents
minimal-history-plugin-favourites dashboard-favourites (read by dashboard-integrations) Starred process definitions, as [{ key, name }]
minimal-history-plugin-integrations-favourites-only dashboard-integrations Whether the integrations list is limited to starred definitions (default true)
minimal-history-plugin-saved-searches-definition-activities definition-historic-activities Saved filter-box searches
minimal-history-plugin-saved-searches-instance-history instance-route-history Saved filter-box searches
minimal-history-plugin-saved-searches-authorizations admin-route-authorization Saved filter-box searches

URL query parameters

The shared settings above can also be set from the URL. The parameters are read from the part of the hash after ?. The boolean parameters are enabled by their mere presence — any value, including none, turns them on. They can only turn a setting on: a setting already stored as true in localStorage stays on whether or not the parameter is in the URL.

Parameter Description
autoRefresh Enable auto-refresh
showHistoricBadges Show historic badges
showSequenceFlow Show executed sequence flows
showHeatmap Show the definition time heatmap
showInstanceHeatmap Show the instance time heatmap
maxResults=N Override max results (e.g. maxResults=500)

Example URL with parameters:

http://localhost:8080/operaton/app/cockpit/default/#/process-instance/123?autoRefresh&showSequenceFlow

Known limitations

These are current gaps, not bugs to report:

  • Signal broadcast is engine-wide. The Signal tab posts to /signal without an execution ID, so it triggers every matching signal catch event in every deployed process definition, not only in the definition you are looking at. The engine offers no way to query that set, so the dry run lists instances of the current definition only and says so; the real reach is wider than the list.

  • History queries are capped. History endpoints return at most maxResults records (1000 by default). Raise it with the maxResults setting or URL parameter if you need more. Both history views over-fetch by one record to detect the cap and say so — the instance diagram's toggles turn amber, and the definition Statistics tab shows a warning above the table — because the cap drops the oldest records, which skews the figures towards recent activity rather than merely shortening them.

  • The table counts finished executions; the heatmap counts time being spent. An activity still running has no duration to average or take a median of, so the Statistics table and its count badges cover completed executions only. The heatmap deliberately does not share that filter: it answers where a process is spending time, and a token parked on a task for two days is the truest answer it has, so an unfinished activity contributes the time elapsed since it started. Activities with no name are listed under their element id.

  • The heatmap ranks elements against each other, not against a target. Colour is the element's share of the slowest element's cumulative time, so the hottest spot is always red however fast the process is overall. It answers "where does this process spend its time", not "is this fast enough". Elements that consumed no measurable time — instant start and end events, gateways — get no blob at all, since they have no time to rank. Activities still running do get one, measured against the browser's clock, so a process that has not finished anything yet still shows where its tokens are sitting.

    The two heatmaps answer different questions and have separate toggles and separate settings. On a definition diagram the heat is cumulative across every instance in the current filter, ranking the process's own steps against each other. On an instance's history diagram it is that one run only, which is where a single slow execution shows up that the average hides. Switching one on does not switch on the other.

  • The executed path is inferred, not reported. The engine records which activities ran, never which sequence flows were taken, so the green path is reconstructed from activity timestamps. Exclusive gateways are resolved to the branch taken on each pass. Inclusive and event-based gateways use the plain rule, which handles them: an inclusive gateway draws every branch that fired and not the ones that did not, and for an event-based gateway the engine records nothing at all for the branches that lost, so only the winner is drawn.

  • A long instance is drawn from a partial history. The activity history behind the diagram is bounded by maxResults, oldest first, so an instance with more activity records than that is drawn from a chronological prefix: the path is complete up to a point and then stops, and each traversal count is a lower bound. The plugin says so rather than letting that read as the whole story — the sequence flow toggle turns amber and its tooltip warns, and each path reads "Executed at least N times". Raise maxResults to take in more.

Requirements

  • Operaton or Camunda 7 Cockpit, which passes api.engineApi and related fields to each plugin
  • The REST API reachable from the browser, including the /history/* endpoints used by the history and audit log views
  • Authorizations for whatever a plugin touches. Plugins do not add permissions of their own: a user who cannot modify instances through the REST API cannot modify them through the Modify tab either

Develop it

$ cd operaton-cockpit-plugins
$ npm install
$ npm run watch

npm run watch rebuilds the bundles with sourcemaps on every change. When the scripts are mounted into a running Docker container, changes are visible after a page refresh.

For a complete local stack, devenv.nix runs Operaton with PostgreSQL behind a Caddy proxy on port 8000 that serves the configuration files and bundles straight from the repository root:

$ make up      # devenv up
$ npm run watch

Commands

Command Description
npm run build Production bundles (no sourcemaps)
BUILD_PLUGIN=<name> npm run build Build only bundles whose name contains <name>
npm run watch Development build with file watching
npm test Run the Jest test suite
npm run test:coverage Run tests with a coverage report
npm run typecheck TypeScript type checking
npm run lint / npm run lint:fix ESLint
npm run prettier:check / npm run prettier:format Prettier
npm run check typecheck + lint + prettier, all of them
npm run fix lint --fix + prettier --write

Sources live in src/; the top-level *.js files are generated. Edit the sources and rebuild — never edit a bundle by hand. See AGENTS.md for a map of the codebase and its conventions.

About

Minimal "history plugins" for Operaton and Camunda 7 Cockpit

Resources

Stars

85 stars

Watchers

9 watching

Forks

Used by

Contributors

Languages