Skip to content

Add Sankey visualization#26153

Open
dennisoelkers wants to merge 8 commits into
masterfrom
feature/sankey-visualization
Open

Add Sankey visualization#26153
dennisoelkers wants to merge 8 commits into
masterfrom
feature/sankey-visualization

Conversation

@dennisoelkers
Copy link
Copy Markdown
Member

@dennisoelkers dennisoelkers commented May 28, 2026

Description

Adds a new Sankey visualization wrapper around Plotly's sankey trace, registered as a new widget type alongside the other visualizations in bindings.tsx.

  • Renders any pivot config with at least two grouping fields (across multiple groupings or stacked within one). Each additional field produces an extra stage.
  • The first configured metric provides link weights. With no metric configured, every link contributes a static weight of 1.
  • Nodes are clickable and open the standard field/value action menu — same actions a PlotLegend item exposes. Drag handling is disabled (arrangement: 'fixed').
  • Renders a centered "No flows to display" message when the data yields no usable links (empty results, all-null metric values, shape mismatches).
  • Plotly's built-in 500ms fade transition on sankey render/select is disabled by patching sankey/constants.duration to 0 at module-load time.
  • Guards GenericPlot's hover handler against bbox-less events (sankey link hovers emit such events and previously crashed).

Motivation and Context

Fixes Graylog2/graylog-plugin-enterprise#7230.

How Has This Been Tested?

  • New unit tests under sankey/__tests__/ covering link construction, weights, empty states, and click wiring.
  • yarn tsc, yarn lint:changes, and yarn test pass.
  • Manually verified in the dev server against multi-grouping pivots, single grouping with stacked fields, configs with and without a metric, and empty result sets.

Screenshots (if appropriate):

image

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (non-breaking change)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have requested a documentation update.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.

dennisoelkers and others added 8 commits May 27, 2026 16:39
Registers `plotly.js/lib/sankey` in the custom plotly bundle and adds a
new `sankey` visualization wrapper. The widget renders any pivot config
with at least two grouping fields (whether spread across multiple
groupings or stacked within one), with each additional field producing
an extra stage. The first configured metric provides link weights; with
no metric configured, every link contributes a static weight of 1.

Guards `GenericPlot`'s hover handler against events without a `bbox`,
which Plotly emits for sankey link hovers.

Adds `d3-interpolate` and `d3-color` (pure ESM, pulled in transitively
by the sankey trace) to the jest preset's transform allowlist so tests
that render a real `GenericPlot` continue to load.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each sankey node now carries `customdata: { field, value }` so clicking
opens the standard field/value action menu — the same actions that
clicking a `PlotLegend` item opens. Plotly's sankey click emits a
synthetic event with no usable coordinates, so the popover position
comes from a document-level `mousedown` listener captured into a ref.

Disables Plotly's built-in node dragging via `arrangement: 'fixed'`,
and guards `GenericPlot`'s hover handler against events without a
`bbox` (sankey link hovers emit such events and previously crashed).

Shows a centered "No flows to display" message in place of `GenericPlot`
when the data yields no usable links — covers empty results, all-null
metric values, and shape mismatches.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Plotly's sankey trace hard-codes a 500ms d3 transition that fades links
in on initial render and on every node selection. Patch the cached
`sankey/constants` module exports to set `duration = 0` at module-load
time so all `d3.transition().duration(c.duration)` calls inside
`sankey/render.js` become instant.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the homegrown sankey popover hook + dropdown with the shared
`usePlotOnClickPopover` machinery so node clicks open the same standard
value-actions menu used by every other plotly visualization. Adds a
new chart-type branch in the hook that:

  - registers `'sankey'` in `ChartType`
  - resolves the clicked SVG element via `querySelectorAll('.sankey-node')`
    / `.sankey-link` indexed by the point's `pointNumber` (plotly's sankey
    emits a stub `{ target: true }` event so the usual `e.event.target`
    closest-walk doesn't apply)
  - dedupes anchors by element identity so a repeated click on the same
    target doesn't churn `DropdownSwitcher`'s effect

Edges are now clickable too. A new `SankeyOnClickPopover` component
hosts both the value-selection list and the action menu inside a single
`Popover.Dropdown` that never unmounts mid-interaction — this avoids
Mantine's clickOutside detector firing during the dropdown swap that
`DropdownSwitcher` does for the other viz. The wrapper keys the
component on the anchor so internal state resets cleanly on each new
chart click. For nodes (a single field/value) the inner step is
pre-selected so users land on the action menu directly.

For edge clicks, sankey is added to the `multipleValuesActionsSupportedVisualizations`
allowlist so `OnClickPopoverValueGroups` renders the combined-AND row
(e.g. `source_ip:1.1.1.1 AND destination_ip:8.8.8.8`). `GroupingActions`
is taught to accept an optional `metricValue` so the merged-AND target
works for sankeys without a configured metric (it falls back to empty
`field`/`value` — the action handlers read `contexts.valuePath` anyway).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant