Life Expectancy Histogram had the same bug as the earlier Bubble chart
fix: its adhoc filter pointed at 2014, which has zero SP_DYN_LE00_IN data
in the world_health dataset, so the thumbnail showed an empty chart.
Moved it to 2011, which has real data.
Deck.gl GeoJson rendered as a single solid-colored blob: the global
fill_color_picker (alpha=1) always overrides any per-feature fill color,
and line_width defaulted to ~1 meter, invisible at city zoom, so none of
the 25 zip-code boundaries were visible. Baked a population-ranked
choropleth fill-color into each zip code's GeoJSON Feature, set
fill_color_picker's alpha to 0 so the per-feature colors show through,
switched the stroke to a visible white pixel-width line, and turned off
the extruded flag since there's no per-feature elevation data backing it.
Sales Territory Tree Horizontal reuses the same sales_territory_hierarchy
dataset as the existing radial Sales Territory Tree example, but with
layout: orthogonal / orient: LR so the gallery shows tree_chart's other
common orientation instead of two renders of the same radial chart.
The capture tool discovered ~53 viz types across the example dashboards
but only ever captured one representative chart per type into
thumbnail.png; every gallery slot beyond that was hand-made art that
predated any of this, unrelated to what the example dashboards actually
contain. Two of those hand-made images turned out to be faked outright:
ag-grid-table's and cartodiagram's "dark" variants were a naive full-image
color inversion of the light one rather than a real dark-theme render
(confirmed by pixel-diffing every light/dark pair in the repo -- these
two matched a naive invert at 85-99%, every genuine capture matched at
under 2%).
To fix this without silently losing the old art or shipping anything
dishonest:
1. Every existing thumbnail/gallery image was renamed with a
custom_thumb_ prefix (plugin imports updated to match), so it's
preserved and clearly labeled as hand-made rather than captured.
2. The capture script (capture-viz-thumbnails.spec.ts) was generalized:
it now captures every distinct chart per viz type, not just one --
the preferred (or alphabetically-first) chart becomes the picker
thumbnail, and every other distinct chart fills the next
already-declared exampleGallery slot, via a new VIZ_TYPE_GALLERY map
mirroring VIZ_TYPE_THUMBNAILS. Also fixed a pre-existing bug where
VIZ_TYPE_THUMBNAILS.rose pointed at plugin-chart-rose, a package
consolidated into plugin-chart-echarts/src/Rose long ago.
3. Ran it for real against a live instance with examples loaded
(including the new Deck.gl GeoJson example). Every plugin whose
real capture succeeded had its import flipped from the custom_thumb_
file back to the plain, freshly-captured one.
4. For deck.gl chart types, the dark "capture" is confirmed genuinely
pixel-identical to light (they render static map tiles that don't
respond to prefers-color-scheme) rather than skipped/left stale, so
the plain dark file is an honest copy of the real light capture
instead of mismatched old art.
Four viz types still have zero chart on any example dashboard and keep
their custom_thumb_ imports as an honest label rather than a graduated
(but fake) real capture:
- cartodiagram: needs a hand-crafted embedded sub-chart config
- deck_multi: sub-layers are referenced by raw DB-assigned chart ids
with no UUID-based remap path through the YAML importer -- a real
gap needing an importer/exporter fix, not something a fixture alone
can solve
- pop_kpi, ag-grid-table: gated behind ChartPluginsExperimental /
AgGridTableEnabled and unregistered by default, so a default-visible
dashboard chart would just show every regular user a broken card
deck_geojson had zero chart on any example dashboard, needing an example
dataset with a serialized GeoJSON Feature column -- something no
existing example data had. Derived a `geojson` column for
sf_population_polygons (already used by the deck.gl demo dashboard for
deck_polygon/deck_contour) from its existing `contour` point-list
column, wrapping each zip code's boundary as a proper GeoJSON Feature.
Added the chart to Misc Charts and to the dashboard's cross-filter
scope list.
Also carries the world_health bubble_v2 migration + time_range fix
already sent separately to master (#43152); duplicated here so this
branch's own capture tooling and CI have working data independent of
that PR's merge timing.
xAxis.interval was set directly from the xAxisLabelInterval control
('auto'/'0'), but xAxis.interval forces echarts' IntervalScale into a
fixed-tick-spacing mode that expects a number and crashes the axis
"nice" tick calculation. Every bubble_v2 chart hit this at its default
control value; there was no existing test coverage for this file.
The interval belongs nested under axisLabel, where it only controls how
many labels are skipped, matching how every other echarts chart in this
codebase (e.g. Timeseries) wires it. Added a regression test.
Found while building out live thumbnail capture for example dashboards
(this PR) -- bubble_v2 apparently never had a real dashboard-placed
chart to exercise this path before.
aaed1198e21f duplicated master's own resolution (d7cecc48bd55) of the
same two heads (4f145192b583, c4a1b8e2d739); nothing in this branch's
chain depends on it, so it can be dropped outright.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses rusackas's leftover note on #42328: "The handlebars showcase tab
idea (keep the logo, add a Misc tab of CSS-heavy handlebars examples)."
- Kept the existing Sales Handlebars List example (the Superset logo demo)
untouched, per "keep the logo".
- Added a new "Sales Handlebars Showcase" chart: a product-line leaderboard
rendered as cards, using the plugin's actual CSS-heavy capabilities --
the dedicated "CSS Styles" field for card/badge/gradient-bar styling, the
registered `formatNumber` helper, and just-handlebars-helpers'
conditional (`gt`, `eq`) and math (`sum`, `division`, `multiplication`)
helpers for rank medals (top 3), tier badges (Top Seller/Strong/Growing),
and proportional progress bars. The card markup, rank, and badge text
are plain text/emoji and always render; the colors/shape/bars come from
the CSS field and require an administrator to allow `style` elements via
HTML_SANITIZATION_SCHEMA_EXTENSIONS (server-side sanitization strips
`<style>` by default) -- same caveat the control's own tooltip warns
about, documented in the chart's description.
- Restructured misc_charts/dashboard.yaml from a flat grid into two tabs
("Charts" holding all existing content unchanged, "Handlebars Showcase"
holding the new chart), matching the TABS/TAB position-JSON schema real
Superset-authored tabbed dashboards use (e.g. sales_dashboard).
Verified against a local build with the new content loaded: the "Charts"
tab still renders every pre-existing chart, and the new tab renders the
leaderboard correctly in both light and dark app themes (screenshotted,
not just structurally validated) -- caught and fixed one real issue this
way, a rank-number color that inherited the app's dark-mode text color and
went low-contrast against the card background.
Not part of this change: the handlebars plugin's own thumbnail.png
gallery art (the crawler has no VIZ_TYPE_THUMBNAILS entry for handlebars
by design, to preserve the existing logo art) and the separate "gallery
diversification" backlog item from the same PR comment.
Addresses rusackas's own leftover checklist on #42328:
- Waterfall: pointed at a new quarterly_sales_delta dataset (Q2 2003 - Q2
2005 quarter-over-quarter sales change) instead of raw quarterly totals,
which are always positive and rendered as all-green bars regardless of
whether sales actually grew or shrank. The delta metric produces genuine
green/red bars.
- Tree: added a Territory > Country > City sales hierarchy (41 nodes, 3
levels) built from cleaned_sales_data, replacing the tiny 12-node
USA-only example that shipped with this PR.
- Horizon: new Population Growth Horizon example (20 most populous
countries' annual population growth rate, 1960-2014) replacing the old
7-band/2.5-year example that left most of the thumbnail empty; 20 bands
at the default 25px row height now fill the full 512px canvas and show
real oscillation (several countries dip negative).
- deck.gl Heatmap: fixed a real bug -- color_scheme_type was set to
'default_palette', which isn't a valid value in this plugin's control
panel (only 'fixed_color'/'linear_palette' are), so getColorRange()
fell through every switch case and the layer silently rendered with an
undefined colorRange. Set it to 'linear_palette' with the 'fire' scheme,
and raised row_limit from 5,000 to 50,000 (of 261k available rows).
Recaptured thumbnails for exactly these 4 viz types (light + dark, deck.gl
heatmap dark correctly skipped as canvas/theme-invariant) via
capture-viz-thumbnails.spec.ts against a local build with the new examples
loaded, and visually confirmed each one before committing.
A second, smaller conflict landed while pushing the previous rebase
fix: master's Prettier-to-Oxfmt migration touched every plugin
package.json, colliding with this branch's own renames/deletions of
the legacy-prefixed packages.
Resolved:
- Two modify/delete conflicts (legacy-plugin-chart-rose,
legacy-preset-chart-nvd3): kept deleted. Both packages are fully
removed on this branch with no replacement package (Rose now lives
inside plugin-chart-echarts/src/Rose/).
- Five package.json field-reordering conflicts (chord, country-map,
paired-t-test, parallel-coordinates, world-map): master's migration
reordered/added fields (keywords, homepage) on the old legacy-
prefixed paths while this branch had independently reordered the
same renamed files. Reconstructed each to the canonical field order
already used by sibling packages that merged cleanly (partition,
echarts).
- One content conflict in paired-t-test/src/TTestTable.tsx: discarded
master's dead legacy reactable-based sortConfig block, already fully
replaced by this branch's own COMPARATORS object earlier in the same
file.
package-lock.json regenerated via a clean npm install (no
--legacy-peer-deps, after clearing corrupted npm cache entries) to
correctly reflect both the dependency-tree changes from this rebase
and the Oxfmt migration's own devDependency swap (prettier/eslint-
plugin-prettier out, oxfmt in).
The lockfile committed while resolving the last rebase conflict against
master was missing several real transitive dependencies (preact,
@react-spring/*, polished, react-ace, @deck.gl/widgets), which failed
npm ci in CI's frontend-build/docker-build with "Missing: X from lock
file" errors, cascading into pre-commit/cypress/playwright/docker
failures.
Root-caused to two compounding issues on the machine that regenerated
it: a corrupted local npm cache (npm cache verify found and cleaned up
643 bad entries) and the --legacy-peer-deps flag, which does not
auto-install a peer dependency's own transitive deps the way a plain
npm install does -- @deck.gl/widgets is itself a peer dependency, and
preact is one of its own dependencies, so it was silently dropped.
Regenerated cleanly with a plain npm install after clearing the cache;
verified node_modules/preact, node_modules/@react-spring/core, and
node_modules/@deck.gl/widgets are all present this time.
Routine rebase; the only conflict was package-lock.json, regenerated
via npm install against the already-cleanly-merged package.json.
Everything else (package.json, plugin-chart-partition's package.json,
superset/views/base.py, superset/views/core.py,
tests/integration_tests/security_tests.py) merged automatically.
Addresses @sadpandajoe's follow-up review comment on #41714: an
original query_context with "queries": [] backs up as a falsy-but-
present empty list, not None. downgrade_slice's truthiness check
(`if queries_bak:`) treated that the same as "no context was ever
stored" and set query_context to None, discarding the slice's
original datasource and form_data instead of restoring it.
Also fixes the same ambiguity at the source: QUERIES_BAK_FIELD_NAME
defaulted to {} rather than None when absent from form_data, which
could be misread as a real (if malformed) backup rather than "key not
present". Changed to the natural None default so "no backup" and "an
empty list backup" stay distinguishable, and dedented the
query_context assignment that was incorrectly nested inside the
"form_data" in query_context check (a context missing "form_data"
would restore params/viz_type but silently leave query_context at its
upgraded value).
Also updates the stale UPDATING.md note for this PR: the percent-
re-basing and deck_multi autozoom limitations it warned about were
both resolved earlier in this branch.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Enforce DECK_MULTI_MAX_SLICES client-side before fanning out
per-layer metadata/data requests, mirroring the cap the removed
viz.py pipeline used to enforce server-side.
- Accumulate autozoom features by slice_id (bucketed by viz_type)
instead of overwriting by viz_type, so two layers sharing a
viz_type no longer clobber each other's points.
- ChartClient.loadQueryData now posts the built query context at
the top level of the request body (as /api/v1/chart/data expects)
instead of nesting it under a query_context key, and unwraps the
{result: [...]} response shape correctly.
- migrate_viz downgrade no longer discards a hand-edited
query_context that lacks a "queries" key; the whole context is
backed up and restored verbatim in that case.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The merge onto master left two migration heads: this branch's
88360afb61ed (migrate_compare_chart_to_echarts) and master's
e7d93a524ff6 (add_purge_audit_log), from parallel migration work
landing on both sides. Adds the standard no-op merge revision joining
them, generated via `superset db merge` and verified with a clean
`superset db upgrade` from an empty database.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The only real conflict was an import-list collision in
Timeseries/transformProps.ts (this branch's DTTM_ALIAS next to master's
DataRecordValue); kept both. Country-map's regenerated GeoJSON files and
notebook edits from master merged cleanly via rename detection onto this
branch's already-renamed plugin-chart-country-map/ package, with no
overlapping edits to reconcile.
Resolves a conflict in ExploreChartPanel/index.tsx between master's new
standalone-download-control feature and this branch's earlier removal
of the raw core Alert import in favor of the ExploreAlert component:
kept master's URL_PARAMS/getUrlParam/StandaloneDownloadControl wiring,
dropped the reintroduced Alert import since it's unused on this branch.
Resolves conflicts between the async-job-cancellation feature added on
master and this branch's removal of the legacy explore_json pipeline:
kept the cancellation feature (_register_cancellable_job, cancel_job,
is_job_cancelled, the task_id/SIGUSR1 revoke wiring, and its tests) and
dropped the parts of it that only applied to submit_explore_json_job /
load_explore_json_into_cache, which this branch already deleted. Also
merged master's get_request_json_body() hardening in views/utils.py
and its abort-signal wiring in chartAction.ts (adapted to this
branch's already-simplified, useLegacyApi-free handleChartDataResponse
signature).
master added version_transaction_issued_at_index (d3b9a1f6c204) on top of
add_extension_storage_table (e5f6a7b8c9d0), which our bubble-chart migration
was still pointing at as its down_revision -- producing two heads and
failing "superset db upgrade" (and everything downstream: load_examples,
postgres/mysql/sqlite integration tests, cypress, playwright) with
"Multiple head revisions are present". Re-point onto the new head so the
chain is linear again.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This test module imported `superset.viz`, which this PR removes, breaking
unit-test collection. The jinja-preservation regression it guarded is
already covered by
core_tests.py::test_split_adhoc_filters_preserves_jinja_templates against
the new (non-viz.py) code path, so the file is redundant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The explore_json/viz.py removal commit deleted this banner's supporting
state and imports (it only applied to useLegacyApi chart types), but a
rebase conflict against master reintroduced the JSX referencing the
now-undefined vizTypeNeedsDataset/setShowDatasetModal/Alert. Also picks
up a prettier formatting fixup in StatefulChart.tsx.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nothing has registered this package since the Bullet and Time-series
Period Pivot charts moved to ECharts; remove the workspace, its
tsconfig reference, the custom-rules grandfather entry, and its
lockfile entries (which also sweeps the nvd3-only fast-safe-stringify
dependency). The nvd3-fork library itself remains a dependency of
plugin-chart-rose, whose legend and tooltip still use it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The nvd3-fork legend and axis labels render SVG text with the default
black fill, which is unreadable against a dark theme background.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds transformProps-level coverage for rebase_percent_change: series
rebased from the first point with a forced percent axis format, and the
snake_case key the compare-chart migration stores read through real
ChartProps camelization. Also guards the rebase against form data with
no explicit x-axis by falling back to the temporal alias, matching
extractSeries.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Range labels move from mid-bar scatter points onto the markArea bands
(insideTopRight), so each label sits inside the range it names and the
rightmost label no longer clips at the chart edge. The tooltip stays
enabled regardless of the Show labels/legend toggles and the measure bar
tooltip names the range the value falls within. The grid top now
estimates wrapped legend rows from item text widths instead of assuming
a single row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Master's add_extension_storage_table migration landed with revision id
e5f6a7b8c9d0, colliding with the compare-chart migration's id; re-id it
to 88360afb61ed and chain the bubble migration off master's head.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Also retriggers CI so the merge ref picks up the master fix from #42274
(an empty commit does not trigger the path-gated workflows).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The spec's fixture chart was created with params only. Real charts saved
through Explore always persist a query_context, and guest (embedded)
chart data requests are validated against the stored chart: with no
stored query_context and no columns/groupby params keys, the pivot
payload's query columns read as tampering and every request 403s.
The suite previously passed only when the embedded iframe happened to
ride the admin session from storageState instead of the guest token (a
cookie race between the /embedded response's anonymous session and the
SDK's csrf/guest-token fetches), which masked the 403 on master.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Escaping only commas let group tuples like (a\\, b) and (a-comma, b)
flatten to identical column keys; backslashes are now escaped first, with
a regression test pinning the collision pair. The cache warm-up error for
charts whose query context has not been generated yet tells the operator
how to resolve it, and UPDATING.md documents the one-time lazy generation
for charts migrated in place.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lint-frontend's tsc build failed with TS2352 on the direct Accessor ->
ColorAccessor cast; go through unknown first as the compiler suggests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three plugin tests still asserted on ChartMetadata.useLegacyApi, which
this PR drops entirely, and the Arc layer test called deck.gl color
accessors without narrowing their Accessor union type. Both broke
lint-frontend's tsc check.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Arc layer read color_picker/target_color_picker straight off form data
and dereferenced .r/.g/.b, so a saved chart without those controls crashed
the ArcLayer on init ("Cannot read properties of undefined (reading 'r')").
This surfaced in deck.gl Multiple Layers, where sub-slices arrive as raw
saved form data without control-default hydration and the Arc example never
persisted target_color_picker. Fall back to the control-panel default color
(PRIMARY_COLOR) when a picker is absent, matching how Path and Scatter
already guard, and harden Polygon's fill/stroke pickers the same way. Adds
Arc color-accessor tests for the missing and present cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a deck.gl Multiple Layers sub-layer fails to load (e.g. it is bound to
a dataset that lacks the columns it needs), the error previously only threw
to the browser console, leaving the map looking silently empty. Capture the
per-slice failure and render a warning Alert over the map, normalized via
getClientErrorObject so the server message (e.g. "Columns missing in
dataset") is shown. Errors reset on each reload.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov flagged the calendar transformProps and the calendar/chord/
country-map plugin index modules as uncovered. Add plugin-registration
tests (instantiate the plugin, assert v1 metadata and the buildQuery
loader), a calendar transformProps test (v1 reshape plus display-option
passthrough, and the non-array passthrough branch), and a calendar
buildQuery case for an unrecognized subdomain granularity falling back to
minutes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each deck.gl Multiple Layers sub-layer is an independent saved chart with
its own dataset, and its layer query must hit that dataset. fetchSubslices
rebuilt the layer form_data from the saved params, whose `datasource`
string can be stale -- example charts hardcode a datasource id that does
not match the imported dataset's real id. The layer query then went to the
wrong dataset and the server rejected it with 400 "Columns missing in
dataset" (e.g. LON/LAT), so no layer rendered. Standalone the chart works
because it resolves its datasource from the slice relationship, not params.
Use the chart's authoritative datasource_id/datasource_type from the chart
API to build the layer datasource, falling back to params only when absent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The GET_POINTS_BY_VIZ_TYPE map annotated its values as
(features: JsonObject[]) => [number, number][], but the per-layer
getPoints helpers have looser, inconsistent signatures (getPointsGeojson
takes Point[]), so the map failed tsc. Replace it with an explicit-spread
collectPoints(features) mirroring the original getAdjustedViewport, which
type-checks and works for both the payload and the per-layer accumulator.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deck.gl Multiple Layers computed its viewport once, from
props.payload.data.features, and never again. In the v1 path that payload
is empty (each layer is fetched client-side after mount), so autozoom had
no points to fit and the camera stayed at the default location while the
layers rendered off-screen -- the map showed but appeared to have no data.
Accumulate each layer's features as it is fetched and refit the viewport
to the combined points (when autozoom is enabled), mirroring what the
legacy pre-merged payload allowed. Also factor the per-viz_type point
collection into a shared helper. Adds a v1-path test covering both layer
rendering and the viewport refit, which the existing suite (all legacy
payload.data.slices) did not exercise.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nothing in the plugin imports prop-types since the class components were
migrated to function components. Remove it and its lockfile reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The container relied on height: 100%, which does not resolve because the
chart's parent is not height-bounded in the v1 render path, so tall output
(many groups across multiple metrics) still clipped without scrolling.
Thread the explicit height SuperChart passes via chartProps through
transformProps and apply it to the scroll container, matching the pattern
used by the pivot-table chart.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the interim plain-table rendering with the design-system antd Table
from @superset-ui/core/components: native column sorting via the ported
comparators, per-cell lift/p-value/significance coloring through semantic
theme tokens (no bespoke CSS classes), and row-click control selection via
onRow. Removes the reactable dependency entirely (its fragile, React-18-
incompatible rendering was the production bug) and the leftover reactable-*
styling. Also drops the now-stale distributions/cephes lockfile entries.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The container styled the non-existent .scrollbar-container class, so the
chart never scrolled and tall output (many groups across multiple metrics)
was clipped with no way to reach the rest. Make the chart root fill its
allotted height and scroll on overflow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The migrated chart returned correct data (verified end-to-end) yet showed
table headers with no body rows in production builds, while every jest
path rendered rows. The common factor was reactable, an unmaintained 2016
library that relies on React-18-incompatible legacy lifecycles
(componentWillMount/componentWillReceiveProps) and identifies its row
children by stringifying components -- fragile in a production bundle.
Replace it with a plain semantic table that reproduces every behavior
(control-row selection, per-cell lift/p-value/significance coloring, and
the same column sort comparators), reusing the existing CSS class hooks so
the surrounding styles are unchanged. Rendering is now deterministic and
fully unit-testable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The legacy-pipeline removal deleted useLegacyApi from ChartMetadataConfig;
the enableNoResults test still passed it, breaking tsc in lint-frontend.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Guards the "headers render but no body rows" failure mode by driving the
real transformProps -> PairedTTest pipeline with a realistic flat
/api/v1/chart/data timeseries response (main.birth_names shape): asserts
transformProps keys the reshaped data by metric label with one series per
group tuple, and that the rendered tables contain a body row per group,
including when optional precision/significance controls are absent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChartRenderer computed the SuperChart enableNoResults prop purely from
server-pagination + AG Grid filter state (bypassNoResult) and never read
the chart plugin's own enableNoResults metadata. Charts that fetch their
own data and issue no top-level query, like deck.gl Multiple Layers, set
enableNoResults: false but still hit the "No results were returned for
this query" empty state in explore, which pre-empts their self-fetching
renderer from ever mounting.
AND the chart's enableNoResults metadata (defaulting to true) into
bypassNoResult so deck_multi and similar self-fetching charts render.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds low-risk import-and-assert tests across migrated plugins, guarding the
classes of bugs found while testing this branch:
- is_timeseries charts must expose a datetime control (calendar, horizon, rose,
partition). Partition genuinely lacked one, so add sections.legacyTimeseriesTime
to its control panel (same 500 as paired-t-test otherwise).
- deck.gl Multiple Layers must issue an empty query (self-fetches its layers).
- deck.gl Arc is timeseries only when time_grain_sqla is set.
- Time Pivot's numeric x-axis format must render a number, not the literal
SMART_NUMBER string.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removing the distributions dependency left TTestTable.test.tsx mocking a module
the component no longer imports, so the p-value/significance tests failed. Mock
./statistics.studentTwoSidedPValue to a deterministic 0.02 instead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Time Pivot's x-axis is a numeric offset within the period (its x_axis_format
defaults to SMART_NUMBER), but NVD3Vis ran it through getTimeFormatter, which
made d3 print the literal string "SMART_NUMBER" on every tick. Format it as a
number instead. (Pre-existing bug, bycatch.)
- SelectAsyncControl never forwarded the Select 'oneLine' prop, so many selected
tags wrapped outside the control's fixed-height box (visible on deck.gl
Multiple Layers). Pass oneLine for multi mode so tags collapse to a '+N' tag.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The chart imported 'distributions' to compute the Student's t p-value, but that
package references Node's Buffer global, which is only polyfilled in dev builds
-- so the chart rendered in dev and threw "ReferenceError: Buffer is not
defined" in production. Replace it with a self-contained, browser-safe
two-sided p-value via the regularized incomplete beta function, verified
against standard t-table critical values, and drop the dependency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deck.gl Multiple Layers issues no query of its own -- each layer is a saved
chart that fetches its data client-side, so buildQuery is intentionally empty.
Dropping useLegacyApi exposed the default enableNoResults=true, so the empty
query response now shows "No results were returned for this query" and the map
never renders. Set enableNoResults: false, matching the other self-fetching
charts (Select filter, DeckglLayerVisibility).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The paired t-test chart's buildQuery sends is_timeseries, so the backend
requires a datetime column, but its migrated control panel has no time
section. Creating the chart fails with "Datetime column not provided as part
table configuration and is required by this type of chart" with no way to
supply one. Add the shared legacyTimeseriesTime section, matching its sibling
timeseries charts (rose, horizon), so a granularity column can be selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
master added strip_metricsqlexpressions_from_ag_grid_params (d24e6b0a9c7f)
on top of shadow_live_row_indexes (8f3a1b2c4d5e) after this branch's
bubble-chart migration was last pointed at 8f3a1b2c4d5e, producing two
alembic heads and failing `db upgrade` across every integration/E2E job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops the dead `method` param from getChartDataRequest (the legacy
GET/POST branching it supported no longer exists now that chart data
always POSTs to /api/v1/chart/data), removes bubble-only NVD3Vis props
(entity/maxBubbleSize/xField/yField/sizeField) and the unused module-level
`formatter` left over from the bubble->bubble_v2 migration, and deletes
plugins/legacy-preset-chart-nvd3/test/TimePivot/controlPanel.test.ts, an
orphaned test for a src/ directory that no longer exists after the
rename to preset-chart-nvd3 (superseded by
plugins/preset-chart-nvd3/test/TimePivot.test.ts).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
down_revision on d4e5f6a7b8c9 pointed at b1c2d3e4f5a6
(add_subjects_tables), which already has a child on master
(56cd24c07170 -> 8f3a1b2c4d5e). That left two alembic heads and
broke `superset db upgrade` in every DB-backed CI job. Chain the
migration after 8f3a1b2c4d5e, master's real current head, instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
down_revision on d4e5f6a7b8c9 still pointed at 3a8e6f2c1b95, which
master's add_subjects_tables migration (b1c2d3e4f5a6) also forked
from, leaving two alembic heads and breaking `superset db upgrade`
in every DB-backed CI job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Multi.tsx now resolves sublayer buildQuery/transformProps via the chart
plugin registries instead of the removed legacy explore.ts helper; update
the color test's mocks to register deck_scatter/deck_arc stubs and mock
SupersetClient.post (matching the new fetch call) instead of .get.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove dangling package-lock.json link entries for the removed
legacy-* plugin workspaces and regenerate entries for their
renamed plugin-chart-* counterparts; npm ci was failing with
EUSAGE because the lockfile referenced workspace paths that no
longer exist on disk.
- Re-parent the bubble-chart-to-echarts migration
(d4e5f6a7b8c9) onto the current single migration head
(3a8e6f2c1b95) instead of a now-superseded ancestor, resolving
the "Multiple head revisions" alembic error that was failing
test-sqlite/test-postgres/test-mysql/cypress/playwright.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Working documents for the remove-legacy-viz-pipeline feature branch;
stripped before final merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing has registered this package since the Bullet and Time-series
Period Pivot charts moved to ECharts; remove the workspace, its
tsconfig reference, the custom-rules grandfather entry, and its
lockfile entries (which also sweeps the nvd3-only fast-safe-stringify
dependency). The nvd3-fork library itself remains a dependency of
plugin-chart-rose, whose legend and tooltip still use it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Master's #41996 relocated legacy filter sanitization out of viz.py and
utils/core.py into the legacy explore path this branch removes; the
remaining utils signature change merges cleanly, viz.py stays deleted,
and the new test file importing superset.viz is removed with it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every thumbnail regenerated from the tuned example charts on the
white/dark card background users actually see, including the restored
generic handlebars logo and a predictive-forecast generic time-series
thumbnail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nineteen additional Misc Charts examples modeling each chart type at
its most recognizable: simpler chord, YoY big number, triangular
funnel, multi-range gauge, compact heatmap grid, bell-curve histogram,
dual-axis bar+line mixed chart, labeled donut, video-game-sales radar,
sunburst with total, stacked area and bars, low-series marker lines
(straight, smooth, stepped), high-cardinality treemap, quarterly
waterfall, multi-metric table and a cell-highlighted pivot. Also tunes
existing examples: monthly-grain period pivot, sales-based time table,
tighter parallel coordinates, recentered point cluster map, and
deck.gl hexagon/scatter viewports pinned (autozoom off) for the
downtown 3D view.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captures now paint the dashboard card background (white or dark) over
explore's gray layout background, hover a populated cell before the
still for charts whose identity benefits from a visible tooltip
(calendar heatmap), and prefer the purpose-built thumbnail examples for
every tuned viz type. Handlebars is intentionally unmapped so its
generic logo survives.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The nvd3-fork legend and axis labels render SVG text with the default
black fill, which is unreadable against a dark theme background.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolves StatefulChart/chartAction conflicts by keeping master's async
(202) handling and staleness guards with the legacy explore_json paths
stripped: the endpoint is always /api/v1/chart/data, the async handler
loses its useLegacyApi parameter, and the legacy body-wrapping branch
and its test are removed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both render without svg/canvas/table, so the crawler needs the looser
rendered signal when capturing them from a flag-enabled environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Removes 30 thumbnailLarge.png files no plugin imports, and captures
live thumbnails (light and dark) for the generic/smooth/step time
series, handlebars, deck.gl contour and heatmap, and point cluster map
from their new example charts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds Misc Charts examples for the generic, smooth and stepped
time-series lines, handlebars, deck.gl contour and heatmap layers, and
the point cluster map (on the keyless maplibre renderer). Flag-gated
types (pop_kpi behind ChartPluginsExperimental, ag-grid-table behind
AgGridTableEnabled) are deliberately excluded: their plugins are
unregistered on default deployments, where their charts would render as
errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerates thumbnails (light and dark) for every viz type on the
example dashboards via the thumbnail crawler, replaces the obsolete
nvd3-era Bullet/TimePivot/TimeTable example gallery screenshots, and
adds a percent-change example (Line3) to the Line chart gallery.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds an explicit navigation timeout so one hung load cannot stall the
crawl until the test timeout, raises the overall budget to 90 minutes,
and gives markup-only charts (big_number_total, handlebars) a looser
rendered signal since they produce no svg/canvas/table for the default
selector to match.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On warm explore navigations getOption() can be undefined or empty when
the baseline effect first runs, crashing the chart render with 'Cannot
read properties of undefined (reading series)'. Guard the read and retry
installation once the chart finishes rendering.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every capture now also renders a dark version via prefers-color-scheme
emulation when the plugin ships a -dark sibling (or the image is new),
skipping the write when the app ignores the emulation so real dark art
is never clobbered with light captures. The Bullet, TimePivot and
TimeTable example.jpg gallery images — still screenshots of the removed
nvd3 renderers — are refreshed as wide extra captures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Instead of enumerating charts, the tool discovers every chart on every
dashboard via the API and captures one representative per viz type, so
it keeps working as example dashboards evolve. The only static piece is
the viz-type-to-image-path map (one line per plugin); unmapped viz types
are reported without failing. Supports VIZ_TYPES=a,b filtering, a
preferred-slice override per type, and named extra captures for gallery
images like the Line percent-change example.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A CAPTURE_THUMBNAILS-gated Playwright spec that renders each migrated
legacy chart's example standalone at 512x512 and overwrites the plugin's
gallery thumbnail, plus an npm run playwright:thumbnails entry point.
Covers the Misc Charts examples and the existing chord, horizon,
parallel coordinates, country map and world map examples; the Line
percent-change capture lands as a new gallery image to be registered in
the plugin metadata after capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds example charts for every migrated legacy visualization that had no
example instance: calendar heatmap, nightingale rose, partition, paired
t-test, bullet, time-series period pivot, a percent-change line, and a
time table. Country map, parallel coordinates, chord, horizon and world
map already have examples in other dashboards.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds transformProps-level coverage for rebase_percent_change: series
rebased from the first point with a forced percent axis format, and the
snake_case key the compare-chart migration stores read through real
ChartProps camelization. Also guards the rebase against form data with
no explicit x-axis by falling back to the temporal alias, matching
extractSeries.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Range labels move from mid-bar scatter points onto the markArea bands
(insideTopRight), so each label sits inside the range it names and the
rightmost label no longer clips at the chart edge. The tooltip stays
enabled regardless of the Show labels/legend toggles and the measure bar
tooltip names the range the value falls within. The grid top now
estimates wrapped legend rows from item text widths instead of assuming
a single row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Master's add_extension_storage_table migration landed with revision id
e5f6a7b8c9d0, colliding with the compare-chart migration's id; re-id it
to 88360afb61ed and chain the bubble migration off master's head.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Also retriggers CI so the merge ref picks up the master fix from #42274
(an empty commit does not trigger the path-gated workflows).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The spec's fixture chart was created with params only. Real charts saved
through Explore always persist a query_context, and guest (embedded)
chart data requests are validated against the stored chart: with no
stored query_context and no columns/groupby params keys, the pivot
payload's query columns read as tampering and every request 403s.
The suite previously passed only when the embedded iframe happened to
ride the admin session from storageState instead of the guest token (a
cookie race between the /embedded response's anonymous session and the
SDK's csrf/guest-token fetches), which masked the 403 on master.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Escaping only commas let group tuples like (a\\, b) and (a-comma, b)
flatten to identical column keys; backslashes are now escaped first, with
a regression test pinning the collision pair. The cache warm-up error for
charts whose query context has not been generated yet tells the operator
how to resolve it, and UPDATING.md documents the one-time lazy generation
for charts migrated in place.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lint-frontend's tsc build failed with TS2352 on the direct Accessor ->
ColorAccessor cast; go through unknown first as the compiler suggests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three plugin tests still asserted on ChartMetadata.useLegacyApi, which
this PR drops entirely, and the Arc layer test called deck.gl color
accessors without narrowing their Accessor union type. Both broke
lint-frontend's tsc check.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Arc layer read color_picker/target_color_picker straight off form data
and dereferenced .r/.g/.b, so a saved chart without those controls crashed
the ArcLayer on init ("Cannot read properties of undefined (reading 'r')").
This surfaced in deck.gl Multiple Layers, where sub-slices arrive as raw
saved form data without control-default hydration and the Arc example never
persisted target_color_picker. Fall back to the control-panel default color
(PRIMARY_COLOR) when a picker is absent, matching how Path and Scatter
already guard, and harden Polygon's fill/stroke pickers the same way. Adds
Arc color-accessor tests for the missing and present cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a deck.gl Multiple Layers sub-layer fails to load (e.g. it is bound to
a dataset that lacks the columns it needs), the error previously only threw
to the browser console, leaving the map looking silently empty. Capture the
per-slice failure and render a warning Alert over the map, normalized via
getClientErrorObject so the server message (e.g. "Columns missing in
dataset") is shown. Errors reset on each reload.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov flagged the calendar transformProps and the calendar/chord/
country-map plugin index modules as uncovered. Add plugin-registration
tests (instantiate the plugin, assert v1 metadata and the buildQuery
loader), a calendar transformProps test (v1 reshape plus display-option
passthrough, and the non-array passthrough branch), and a calendar
buildQuery case for an unrecognized subdomain granularity falling back to
minutes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each deck.gl Multiple Layers sub-layer is an independent saved chart with
its own dataset, and its layer query must hit that dataset. fetchSubslices
rebuilt the layer form_data from the saved params, whose `datasource`
string can be stale -- example charts hardcode a datasource id that does
not match the imported dataset's real id. The layer query then went to the
wrong dataset and the server rejected it with 400 "Columns missing in
dataset" (e.g. LON/LAT), so no layer rendered. Standalone the chart works
because it resolves its datasource from the slice relationship, not params.
Use the chart's authoritative datasource_id/datasource_type from the chart
API to build the layer datasource, falling back to params only when absent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The GET_POINTS_BY_VIZ_TYPE map annotated its values as
(features: JsonObject[]) => [number, number][], but the per-layer
getPoints helpers have looser, inconsistent signatures (getPointsGeojson
takes Point[]), so the map failed tsc. Replace it with an explicit-spread
collectPoints(features) mirroring the original getAdjustedViewport, which
type-checks and works for both the payload and the per-layer accumulator.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deck.gl Multiple Layers computed its viewport once, from
props.payload.data.features, and never again. In the v1 path that payload
is empty (each layer is fetched client-side after mount), so autozoom had
no points to fit and the camera stayed at the default location while the
layers rendered off-screen -- the map showed but appeared to have no data.
Accumulate each layer's features as it is fetched and refit the viewport
to the combined points (when autozoom is enabled), mirroring what the
legacy pre-merged payload allowed. Also factor the per-viz_type point
collection into a shared helper. Adds a v1-path test covering both layer
rendering and the viewport refit, which the existing suite (all legacy
payload.data.slices) did not exercise.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nothing in the plugin imports prop-types since the class components were
migrated to function components. Remove it and its lockfile reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The container relied on height: 100%, which does not resolve because the
chart's parent is not height-bounded in the v1 render path, so tall output
(many groups across multiple metrics) still clipped without scrolling.
Thread the explicit height SuperChart passes via chartProps through
transformProps and apply it to the scroll container, matching the pattern
used by the pivot-table chart.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the interim plain-table rendering with the design-system antd Table
from @superset-ui/core/components: native column sorting via the ported
comparators, per-cell lift/p-value/significance coloring through semantic
theme tokens (no bespoke CSS classes), and row-click control selection via
onRow. Removes the reactable dependency entirely (its fragile, React-18-
incompatible rendering was the production bug) and the leftover reactable-*
styling. Also drops the now-stale distributions/cephes lockfile entries.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The container styled the non-existent .scrollbar-container class, so the
chart never scrolled and tall output (many groups across multiple metrics)
was clipped with no way to reach the rest. Make the chart root fill its
allotted height and scroll on overflow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The migrated chart returned correct data (verified end-to-end) yet showed
table headers with no body rows in production builds, while every jest
path rendered rows. The common factor was reactable, an unmaintained 2016
library that relies on React-18-incompatible legacy lifecycles
(componentWillMount/componentWillReceiveProps) and identifies its row
children by stringifying components -- fragile in a production bundle.
Replace it with a plain semantic table that reproduces every behavior
(control-row selection, per-cell lift/p-value/significance coloring, and
the same column sort comparators), reusing the existing CSS class hooks so
the surrounding styles are unchanged. Rendering is now deterministic and
fully unit-testable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The legacy-pipeline removal deleted useLegacyApi from ChartMetadataConfig;
the enableNoResults test still passed it, breaking tsc in lint-frontend.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Guards the "headers render but no body rows" failure mode by driving the
real transformProps -> PairedTTest pipeline with a realistic flat
/api/v1/chart/data timeseries response (main.birth_names shape): asserts
transformProps keys the reshaped data by metric label with one series per
group tuple, and that the rendered tables contain a body row per group,
including when optional precision/significance controls are absent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChartRenderer computed the SuperChart enableNoResults prop purely from
server-pagination + AG Grid filter state (bypassNoResult) and never read
the chart plugin's own enableNoResults metadata. Charts that fetch their
own data and issue no top-level query, like deck.gl Multiple Layers, set
enableNoResults: false but still hit the "No results were returned for
this query" empty state in explore, which pre-empts their self-fetching
renderer from ever mounting.
AND the chart's enableNoResults metadata (defaulting to true) into
bypassNoResult so deck_multi and similar self-fetching charts render.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds low-risk import-and-assert tests across migrated plugins, guarding the
classes of bugs found while testing this branch:
- is_timeseries charts must expose a datetime control (calendar, horizon, rose,
partition). Partition genuinely lacked one, so add sections.legacyTimeseriesTime
to its control panel (same 500 as paired-t-test otherwise).
- deck.gl Multiple Layers must issue an empty query (self-fetches its layers).
- deck.gl Arc is timeseries only when time_grain_sqla is set.
- Time Pivot's numeric x-axis format must render a number, not the literal
SMART_NUMBER string.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removing the distributions dependency left TTestTable.test.tsx mocking a module
the component no longer imports, so the p-value/significance tests failed. Mock
./statistics.studentTwoSidedPValue to a deterministic 0.02 instead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Time Pivot's x-axis is a numeric offset within the period (its x_axis_format
defaults to SMART_NUMBER), but NVD3Vis ran it through getTimeFormatter, which
made d3 print the literal string "SMART_NUMBER" on every tick. Format it as a
number instead. (Pre-existing bug, bycatch.)
- SelectAsyncControl never forwarded the Select 'oneLine' prop, so many selected
tags wrapped outside the control's fixed-height box (visible on deck.gl
Multiple Layers). Pass oneLine for multi mode so tags collapse to a '+N' tag.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The chart imported 'distributions' to compute the Student's t p-value, but that
package references Node's Buffer global, which is only polyfilled in dev builds
-- so the chart rendered in dev and threw "ReferenceError: Buffer is not
defined" in production. Replace it with a self-contained, browser-safe
two-sided p-value via the regularized incomplete beta function, verified
against standard t-table critical values, and drop the dependency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deck.gl Multiple Layers issues no query of its own -- each layer is a saved
chart that fetches its data client-side, so buildQuery is intentionally empty.
Dropping useLegacyApi exposed the default enableNoResults=true, so the empty
query response now shows "No results were returned for this query" and the map
never renders. Set enableNoResults: false, matching the other self-fetching
charts (Select filter, DeckglLayerVisibility).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The paired t-test chart's buildQuery sends is_timeseries, so the backend
requires a datetime column, but its migrated control panel has no time
section. Creating the chart fails with "Datetime column not provided as part
table configuration and is required by this type of chart" with no way to
supply one. Add the shared legacyTimeseriesTime section, matching its sibling
timeseries charts (rose, horizon), so a granularity column can be selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
master added strip_metricsqlexpressions_from_ag_grid_params (d24e6b0a9c7f)
on top of shadow_live_row_indexes (8f3a1b2c4d5e) after this branch's
bubble-chart migration was last pointed at 8f3a1b2c4d5e, producing two
alembic heads and failing `db upgrade` across every integration/E2E job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops the dead `method` param from getChartDataRequest (the legacy
GET/POST branching it supported no longer exists now that chart data
always POSTs to /api/v1/chart/data), removes bubble-only NVD3Vis props
(entity/maxBubbleSize/xField/yField/sizeField) and the unused module-level
`formatter` left over from the bubble->bubble_v2 migration, and deletes
plugins/legacy-preset-chart-nvd3/test/TimePivot/controlPanel.test.ts, an
orphaned test for a src/ directory that no longer exists after the
rename to preset-chart-nvd3 (superseded by
plugins/preset-chart-nvd3/test/TimePivot.test.ts).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
down_revision on d4e5f6a7b8c9 pointed at b1c2d3e4f5a6
(add_subjects_tables), which already has a child on master
(56cd24c07170 -> 8f3a1b2c4d5e). That left two alembic heads and
broke `superset db upgrade` in every DB-backed CI job. Chain the
migration after 8f3a1b2c4d5e, master's real current head, instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
down_revision on d4e5f6a7b8c9 still pointed at 3a8e6f2c1b95, which
master's add_subjects_tables migration (b1c2d3e4f5a6) also forked
from, leaving two alembic heads and breaking `superset db upgrade`
in every DB-backed CI job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Multi.tsx now resolves sublayer buildQuery/transformProps via the chart
plugin registries instead of the removed legacy explore.ts helper; update
the color test's mocks to register deck_scatter/deck_arc stubs and mock
SupersetClient.post (matching the new fetch call) instead of .get.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove dangling package-lock.json link entries for the removed
legacy-* plugin workspaces and regenerate entries for their
renamed plugin-chart-* counterparts; npm ci was failing with
EUSAGE because the lockfile referenced workspace paths that no
longer exist on disk.
- Re-parent the bubble-chart-to-echarts migration
(d4e5f6a7b8c9) onto the current single migration head
(3a8e6f2c1b95) instead of a now-superseded ancestor, resolving
the "Multiple head revisions" alembic error that was failing
test-sqlite/test-postgres/test-mysql/cypress/playwright.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Working documents for the remove-legacy-viz-pipeline feature branch;
stripped before final merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 17:50:32 -07:00
1184 changed files with 43965 additions and 7614 deletions
--title "Scheduled Docker image refresh failed for ${LATEST_RELEASE}" \
--label "infra:container" \
--label "bug" \
--label "#bug" \
--body "The weekly Docker base-image refresh failed for release \`${LATEST_RELEASE}\`. Published images may be missing upstream base-layer security patches until this is resolved.
# zizmor: ignore[dangerous-triggers] - runs in base-branch context and only consumes artifacts uploaded by Python-Unit; never checks out PR code (see note below)
workflow_run:
workflows:["Python-Unit"]
types:[completed]
# This workflow publishes a check run annotating failing Python unit tests
# inline on the PR diff, using JUnit XML uploaded by the Python-Unit workflow.
# It uses the workflow_run trigger so that it always runs in the base-branch
# context and can safely be granted write permissions, even for PRs from
# forks or Dependabot.
#
# IMPORTANT: This workflow must NEVER check out code from the PR branch. All
# data comes from artifacts uploaded by the Python-Unit workflow.
@@ -24,7 +24,80 @@ assists people when migrating to a new version.
## Next
### OAuth2 database callback metrics include their outcome
The unqualified `DatabaseRestApi.oauth2` StatsD counter has been replaced with
`DatabaseRestApi.oauth2.success`, `DatabaseRestApi.oauth2.warning`, and
`DatabaseRestApi.oauth2.error`. Update monitoring rules and dashboards that consume
the old counter to use the outcome-specific replacements.
- [42935](https://github.com/apache/superset/pull/42935): The MCP service now refuses to start (`MCPAuthConfigError`) when `MCP_JWT_ISSUER` trusts more than one issuer and no `MCP_USER_RESOLVER` is configured, instead of only logging a warning. This was already a documented misconfiguration (the default resolver isn't issuer-scoped, so distinct trusted issuers minting the same username/email would resolve to the same Superset user); deployments trusting multiple issuers must configure an `MCP_USER_RESOLVER` that derives its identity from the token's `iss` claim before upgrading. Single-issuer deployments are unaffected.
- [42393](https://github.com/apache/superset/pull/42393): Exported dataset YAML now carries a `uuid` for each metric and column so that custom folder assignments (which reference metrics/columns by UUID) survive an import into another workspace. This affects any export bundle that contains datasets, not just a dataset export: chart, dashboard, database and full-asset exports all embed the same dataset YAML, so a dashboard exported from this release also fails to import into an older one even though no dataset was exported directly. As with `folders` and `currency_code_column`, the affected `datasets/` files fail schema validation (`Unknown field: uuid`) when imported into Superset releases that predate this change; regenerate or hand-edit exports for older targets in mixed-version fleets.
- [42300](https://github.com/apache/superset/pull/42300): Timeseries charts (line/area/bar) with a Y-axis bound in effect — either an explicit `yAxisBounds` or one derived from `truncateYAxis` — now clamp out-of-range data points to that bound instead of letting ECharts drop the point (and the line segments around it) entirely. Any existing chart with a configured Y-axis bound and data outside it will look different after upgrading: a gap becomes a point pinned to the boundary. The clamp also rewrites the value ECharts reads for that point's tooltip and data label, so the displayed value is the bound rather than the true observation.
- [42087](https://github.com/apache/superset/pull/42087): Stored calculated-column and metric expressions are validated when a query is built, under the same sub-query policy already applied to adhoc expressions. Previously only the dataset update path checked them on save, so expressions written by v1 import, by dataset duplication, or before that check existed were never validated. Since `ALLOW_ADHOC_SUBQUERY` defaults to `False` (see [19242](https://github.com/apache/superset/pull/19242)), a dataset whose stored expression contains a sub-query works before upgrading and afterwards fails at chart render with `Custom SQL fields cannot contain sub-queries.` There is no migration step, and the error does not name the offending dataset column, so audit stored expressions before upgrading: either rewrite them without the sub-query, or set `ALLOW_ADHOC_SUBQUERY = True` to keep the previous behaviour for both stored and adhoc expressions.
### Selenium support removed — Playwright is now required for screenshots
Selenium support has been removed. **Playwright is now required** for all
report and thumbnail screenshot generation. Install it with:
`EXCEL_EXPORT_TABLE_VIZ_TYPES`, and `EXCEL_EXPORT_QUERY_CONTEXT_BUILDER`.
The feature depends on `boto3`, which is **not** installed by default; install it
with `pip install apache-superset[excel-export]`.
Charts store their `query_context` only once they have been (re-)saved in
Explore, so older charts may have none. For a fixed, conservative set of viz
types (`table`, `big_number_total`, `big_number`, `pie`) the export rebuilds a
query context from the chart's saved form data so those charts still export.
The rebuild is a single-query mapping and does **not** reproduce plugin
post-processing (pivot, rolling, forecast) or multi-query charts, so any chart of
another type without a saved query context is skipped and listed in the email for
the user to re-save. To cover those types, set `EXCEL_EXPORT_QUERY_CONTEXT_BUILDER`
to a callable that receives the chart's form data and returns a query-context
payload (or `None` to fall back to the built-in rebuild) — for example one backed
by a service that runs the chart's real frontend `buildQuery`.
A second mode, **Export Images to Excel**, embeds non-table charts as rendered
images (which viz types stay tabular is controlled by
`EXCEL_EXPORT_TABLE_VIZ_TYPES`). It renders through the headless webdriver, so the
@@ -766,6 +903,8 @@ With the flag enabled: `DELETE /api/v1/chart/<id>` no longer hard-deletes the ch
- [39914](https://github.com/apache/superset/pull/39914) `ALERT_REPORT_SLACK_V2` now defaults to `True` and the legacy Slack v1 integration (`Slack` recipient type, `files.upload` API) is deprecated for removal in the next major. Slack blocked new apps from `files.upload` in May 2024 and fully retired the method for all apps on November 12, 2025; because the v1 path sends files through `files.upload`, v1 file-bearing sends now fail at the API level — only text-only `chat_postMessage` still works via the legacy path. Grant your Slack bot the `channels:read` and `groups:read` scopes so existing `Slack` recipients can be auto-upgraded to `SlackV2` on next send. Operators who explicitly override the flag to `False`, or whose Slack bot is missing those scopes, will see deprecation warnings while text-only sends continue through the legacy path.
- [42089](https://github.com/apache/superset/pull/42089) automatically upgrades resolvable Slack v1 recipients, preserves text-only v1 delivery with execution warnings when migration cannot finish, and rejects retired v1 file uploads with actionable scope guidance. Slack delivery uses at-most-once terminal writes and a schedule-wide retry budget configured by `SLACK_SEND_RETRY_MAX_TIME`, clamped to the report's remaining working timeout. Deployments using `SupersetMetastoreCache` for the Slack channel cache must schedule the `slack.cache_channels` Celery task to repopulate misses outside report transactions; see [Alerts and Reports](https://superset.apache.org/admin-docs/configuration/alerts-reports#slack-delivery-timeouts-and-retries).
### Soft delete and restore for dashboards
**Everything in this section applies only when the `SOFT_DELETE` feature flag is enabled. The flag defaults to `False`** (`@lifecycle: development`), so on a default deployment `DELETE /api/v1/dashboard/<id>` continues to **hard-delete permanently** — nothing is recoverable. Enable `SOFT_DELETE` to get the behavior described below.
When enabled, Superset rejects webhook configurations that use `http://` URLs.
#### Request Timeout
Webhook deliveries use a socket timeout so a request can't hang forever if the webhook target is unreachable, which would otherwise leave the report schedule stuck in a `WORKING` state. Configure it with:
```python
ALERT_REPORTS_WEBHOOK_TIMEOUT = 60 # seconds
```
Set to `None` to disable the timeout (not recommended).
#### Retry Behavior
Superset automatically retries webhook deliveries on `429 Too Many Requests` and `5xx` server errors using exponential backoff. Retries are bounded to roughly 120 seconds of cumulative wall-clock time (worst case ~210 seconds, because the bound is checked against the time elapsed before each attempt, so the final request can begin just under the limit and still run its full request timeout), after which the delivery is abandoned.
This will cache the top 5 most popular dashboards every hour. For other
strategies, check the `superset/tasks/cache.py` file.
### Warming Up Native Filter Options
Native filter Value-type dropdown option queries (e.g. `SELECT DISTINCT column FROM table`) are
cached the same way as chart data, via `DATA_CACHE_CONFIG`. However, the strategies above only warm
up chart render queries, so the first user to open a dashboard's filter dropdown after a cache entry
expires still triggers a fresh database query.
The `native_filter_options` strategy pre-populates the cache for these dropdown queries. It reads
each dashboard's `native_filter_configuration`, builds the same `filter_select` chart-data query the
frontend would send, and executes it as the configured `SUPERSET_CACHE_WARMUP_USER`:
```python
class CustomCeleryConfig(CeleryConfig):
beat_schedule = {
**CeleryConfig.beat_schedule,
'cache-warmup-native-filters': {
'task': 'cache-warmup',
'schedule': crontab(minute=0, hour=3), # daily at 03:00
'kwargs': {
'strategy_name': 'native_filter_options',
'dashboard_ids': [1, 2, 3],
},
},
}
```
Requirements and limitations:
- `SUPERSET_CACHE_WARMUP_USER` must be set to a user with access to the dashboards and datasets
referenced by the native filters.
- `DATA_CACHE_CONFIG` must use a backend that actually persists entries (Redis recommended); the
default `NullCache` discards writes, so warming has nothing to warm. The effective timeout also
needs to be positive — `NATIVE_FILTER_OPTIONS_CACHE_TIMEOUT = -1` disables cache writes for these
queries entirely, even with a working backend.
- Schedule the warm-up at least as often as the effective native filter cache timeout (whichever of
`NATIVE_FILTER_OPTIONS_CACHE_TIMEOUT`, the chart/dataset/database timeout, or `DATA_CACHE_CONFIG`'s
default applies). A looser schedule still leaves a window of cold, unwarmed queries between expiry
and the next run — the daily example above assumes a TTL of a day or more.
- Cache entries are warmed under the warm-up user's own cache partition, the same entry that user
would create by opening the filter dropdown manually. Users with a different role set or row-level
security context may still see a cache miss on first load.
- Cascading/dependent native filters and search-term variants of filter option queries are not
warmed by this strategy.
## Caching Thumbnails
This is an optional feature that can be turned on by activating its [feature flag](/admin-docs/configuration/configuring-superset#feature-flags) on config:
@@ -519,6 +519,30 @@ sh -c "$(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install
For those interested, you may also try out [avn](https://github.com/nvm-sh/nvm#deeper-shell-integration) to automatically switch to the node version that is required to run Superset frontend.
##### zstd
`npm run dev-server` proxies requests to your local Superset server and rewrites the HTML it returns, so it has to decompress responses sent with `Content-Encoding: zstd`. It does that with [`simple-zstd`](https://www.npmjs.com/package/simple-zstd), which wraps the system `zstd` binary instead of bundling one. That binary has to be on your `PATH`:
```bash
# macOS
brew install zstd
# Ubuntu/Debian
sudo apt install zstd
# Windows
choco install zstd
```
`simple-zstd` looks for the binary when it is first imported, not when a response is decompressed, so a missing `zstd` stops the dev server at startup with:
```
Error: Can not access zstd! Is it installed?
at Object.<anonymous> (.../node_modules/simple-zstd/dist/src/index.js:102:11)
```
The message names the dependency, but it surfaces from inside `webpack.proxy-config.js` while the webpack config is loading, which reads like a build-tooling failure rather than a missing system package.
#### Install dependencies
Install third-party dependencies listed in `package.json` via:
@@ -198,7 +198,7 @@ Each component should come with its dedicated storybook file.
**One component per story:** Each storybook file should only contain one component unless substantially different variants are required
**Component variants:** If the component behavior is substantially different when certain props are used, it is best to separate the story into different types. See the `superset-frontend/src/components/Select/Select.stories.tsx` as an example.
**Component variants:** If the component behavior is substantially different when certain props are used, it is best to separate the story into different types. See the `superset-frontend/packages/superset-ui-core/src/components/Select/Select.stories.tsx` as an example.
**Isolated state:** The storybook should show how the component works in an isolated state and with as few dependencies as possible
@@ -165,6 +165,31 @@ You can also certify metrics if you'd like for your team in this view.
- [Blog: Unlocking the Power of Virtual Datasets](https://preset.io/blog/unlocking-the-power-of-virtual-datasets-in-apache-superset/)
:::
### Native filters on semantic views
When the `SEMANTIC_LAYERS` feature flag is enabled, Superset can connect to external semantic layers
(such as dbt Semantic Layer or Cube) and expose their semantic views as data sources alongside your
regular Datasets. Semantic views can be used as filter targets when adding a native (dashboard) filter,
the same way a Dataset can.
To add a filter on a semantic view:
1. Open the dashboard, click the **⋮** (more options) menu, and select **Edit dashboard**.
2. Open the Filter Bar and click **+ Add/Edit Filters**.
3. Add a new filter and, in the datasource dropdown, select a semantic view. Semantic views are listed
alongside datasets and can be identified by their type.
4. Select one of the semantic view's dimensions in the **Column** field, the same way you'd select a
column on a dataset.
5. Configure the remaining filter options (filter type, default value, scope, etc.) and click **Save**.
Any chart on the dashboard that's powered by the same semantic view is filtered by the selected
dimension when the filter is applied.
:::note
Semantic views and native filter support for them are part of the experimental Semantic Layers
feature and require the `SEMANTIC_LAYERS` feature flag to be enabled.
:::
### Creating charts in Explore view
Superset has 2 main interfaces for exploring data:
@@ -303,6 +328,10 @@ Conditional formatting rules highlight cells based on their values. Rules can be
Each rule has a **"Use gradient"** toggle: enabled applies a varying opacity (lighter = further from threshold), disabled applies a solid fill at full opacity regardless of value.
Each rule's color is set with a full color picker rather than a fixed dropdown of presets. Pick any custom color, or use the **Colors** preset swatches, which reference theme tokens (success, warning, error, and their background variants) so a rule's color updates automatically if the active theme changes, including switching between light and dark mode.
When a rule targets a column with an active time comparison, a **Trend colors** preset also appears, letting you color cells green for an increase and red for a decrease (or the reverse).
#### HTML Rendering in Table Cells
Table chart cells can render raw HTML, enabling rich formatting such as hyperlinks, colored badges, and icons directly in the data. Enable this per-column in the chart's **Column Configuration** panel by toggling **Render HTML**.
@@ -129,3 +129,4 @@ The following URL parameters can be passed through the `urlParams` option in `da
- **Guest tokens expire** — their lifetime is controlled by the `GUEST_TOKEN_JWT_EXP_SECONDS` config (default: 5 minutes). Refresh tokens before they expire using a token refresh mechanism in your host app.
- **Row-level security** — pass `rls` rules in the guest token request to restrict which rows are visible to the embedded user.
- **Allowed domains** — restrict which host origins can embed a dashboard by setting **Allowed Domains** per-dashboard in the _Embed_ settings modal. Superset checks the request's `Referer` header against this list before serving the embedded view; an empty list allows any origin, so configure this explicitly for production.
- **Redacted errors** — API responses to a guest token report a generic `An error occurred while fetching the data.` instead of the underlying error, since engine errors quote catalog, schema, table and column names. Errors Superset raises itself — access denials, timeouts, payload validation — keep their message, and the full error is always available in the server logs.
@@ -32,8 +32,13 @@ Notes on the generated workbook:
Excel's 31-character limit; the chart id keeps names unique).
- Charts nested in tabs are included.
- Data reflects the dashboard's active filter state at the time of export.
- A chart with no saved query context is skipped and listed in the email; open
the chart in Explore and re-save it to include it next time.
- A chart with no saved query context (charts only store one once they've been
re-saved in Explore) still exports when it is a `table`, `big_number`,
`big_number_total` or `pie`, by rebuilding the query from the chart's saved
form data. Charts of other types — and charts relying on post-processing the
rebuild can't reproduce — are skipped and listed in the email; open the chart
in Explore and re-save it to include it next time, or configure
`EXCEL_EXPORT_QUERY_CONTEXT_BUILDER`.
- Row counts per sheet are capped the same way as the chart-level CSV/Excel
export (`ROW_LIMIT`, bounded by `SQL_MAX_ROW`), and never exceed Excel's
per-sheet maximum.
@@ -74,6 +79,7 @@ will not register.
| `EXCEL_EXPORT_LINK_TTL_SECONDS` | `86400` | Lifetime of the pre-signed download URL (24h). |
| `EXCEL_EXPORT_S3_CLIENT_KWARGS` | `{}` | Extra kwargs for `boto3.client("s3", ...)` — e.g. `region_name`, or `endpoint_url` for MinIO/LocalStack. |
| `EXCEL_EXPORT_TABLE_VIZ_TYPES` | `None` | Viz types kept tabular in **Export Images to Excel** mode; every other type is embedded as an image. `None` uses the built-in default (`table`, `pivot_table`, `pivot_table_v2`). |
| `EXCEL_EXPORT_QUERY_CONTEXT_BUILDER` | `None` | Optional `Callable[[form_data_dict], dict \| None]` to build a query context for a chart missing a saved one, tried before the built-in form-data rebuild. Point it at a service that runs the chart's real frontend `buildQuery` to faithfully export viz types the built-in rebuild can't handle. Must return `None` when it can't build faithfully, so the export falls back. |
Credentials and region resolve through the standard boto3 chain (environment
variables, shared config, or instance role) unless overridden via
The mobile experience is gated behind the `MOBILE_CONSUMPTION_MODE` feature
flag, which is off by default. Enable it in your `superset_config.py`:
```python
FEATURE_FLAGS = {
"MOBILE_CONSUMPTION_MODE": True,
}
```
With the flag disabled, Superset renders identically at every screen size,
and phones display the desktop layout scaled down (the pre-existing
behavior). The flag also controls whether Superset serves a viewport meta
tag, which is required for mobile browsers to apply the responsive layout
at their native width.
## What works on mobile
| Area | Mobile behavior |
| --- | --- |
| **Dashboards** | Charts stack vertically at full width, sized to the screen. Tab bars are sticky and swipeable. Native filters open in a drawer via the filter icon in the header. |
| **Dashboard list** | Card view with full-width cards; search and filters open in a drawer. |
| **Home** | Recents (dashboards only) and dashboard cards; desktop-only sections are hidden. |
| **Navigation** | A hamburger menu opens a drawer with links to dashboards, theme and language selection, and user info/logout. |
<img src={useBaseUrl("/img/screenshots/mobile/mobile_home.jpg")} alt="The Superset home page on mobile" width="260" />
<img src={useBaseUrl("/img/screenshots/mobile/mobile_nav_drawer.jpg")} alt="The mobile navigation drawer" width="260" />
<img src={useBaseUrl("/img/screenshots/mobile/mobile_unsupported.jpg")} alt="The screen shown for views that are not available on mobile" width="260" />
</div>
## What doesn't work on mobile
Everything not listed above shows a friendly "This view isn't available on
mobile" screen with shortcuts back to dashboards and the home page. That
includes:
- Chart builder (Explore) and chart-level links — chart titles on
dashboards are plain text on mobile, and chart entries are filtered out
of the home page's Recents feed
- SQL Lab and query history
- Creating or editing dashboards, charts, datasets, and databases
- List views other than dashboards (charts, datasets, saved queries, etc.)
- Administrative and settings screens
Editing controls are also removed from the screens that *are* supported:
the dashboard header hides the edit, publish, and favorite controls, and
dashboard/chart kebab menus are reduced to view-oriented actions.
If a device crosses the 768px threshold — for example, rotating a tablet
to landscape or resizing a window — the full desktop experience becomes
available immediately.
## Notes for operators
- The flag is deployment-wide; there is no per-role or per-user targeting.
- Dashboard permalinks and links shared from desktop resolve normally on
mobile as long as they point at dashboards.
- Embedded dashboards are unaffected: the embedded SDK controls its own
layout, and the viewport meta tag is only interpreted by the top-level
page.
- Dashboards loaded with a `standalone` URL param (used for iframe embeds
and kiosk-style displays) always render the desktop layout, regardless
of viewport width, since the standalone chrome doesn't expose the mobile
description: Reference for the built-in D3-based number format presets available on chart metrics and axes
keywords: [number format, d3 format, formatting, duration, memory, length, distance]
---
{/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/}
# Number Formatting
Most chart types expose a **Number format** control (labeled **D3 Format**, **Y Axis Format**, or similar depending on the chart) wherever a metric or numeric axis can be formatted. This is available from the **Customize** tab, or from the metric's popover editor, depending on the chart type. Selecting one of the built-in presets below applies that formatting to the values Superset renders in the chart.
When an axis format control's chart has **Comparison display** set to **Percentage** (e.g. period-over-period comparisons), that control's choices are narrowed to percentage-only presets, hiding `SMART_NUMBER`, `~g`, and the duration/memory/length presets.
You can also type a custom [D3 format string](https://github.com/d3/d3-format) directly into the control if none of the presets fit your needs.
## Built-in presets
### General
| Key | Description |
| --- | --- |
| `SMART_NUMBER` | Adaptive formatting — automatically picks a reasonable precision based on the value |
| `~g` | Original value, using D3's general-format specifier (trims trailing zeros; may switch to exponential notation for very large or small values) |
### D3 format strings
These are raw [D3 format specifiers](https://github.com/d3/d3-format#locale_format). The dropdown shows a live preview of each one against a sample value.
| `MEMORY_TRANSFER_RATE_DECIMAL` | Memory transfer rate in bytes, decimal (`1024B` => `1.024kB/s`) |
| `MEMORY_TRANSFER_RATE_BINARY` | Memory transfer rate in bytes, binary (`1024B` => `1KiB/s`) |
### Distance / length
| Key | Description |
| --- | --- |
| `LENGTH` | Length in meters, converted to kilometers (`12345m` => `12.35km`) |
| `LENGTH_CM_KM` | Length in centimeters, converted to kilometers (`12345678cm` => `123.46km`) |
| `LENGTH_CM_M` | Length in centimeters, converted to meters (`12345cm` => `123.45m`) |
Use these when a metric's underlying values are stored in meters or centimeters but are easier to read at a coarser unit — for example, distances traveled, cable/pipe lengths, or elevation changes.
## Currency
Some chart types also expose currency-specific formatting, including a dynamic mode that reads the currency from a column value. See [Dynamic Currency Formatting](./creating-your-first-dashboard#dynamic-currency-formatting) for details.
"description":"Enable Matrixify feature for matrix-style chart layouts"
},
{
"name":"MOBILE_CONSUMPTION_MODE",
"default":false,
"lifecycle":"development",
"description":"Serve a consumption-only mobile experience (dashboards, dashboard list, and home page) on small screens; other views show a \"not supported on mobile\" screen. Authoring features are hidden on mobile when enabled."
},
{
"name":"OPTIMIZE_SQL",
"default":false,
@@ -221,12 +227,6 @@
"lifecycle":"testing",
"description":"When impersonating a user, use the email prefix instead of username"
},
{
"name":"PLAYWRIGHT_REPORTS_AND_THUMBNAILS",
"default":false,
"lifecycle":"testing",
"description":"Replace Selenium with Playwright for reports and thumbnails. Supports deck.gl visualizations. Requires playwright pip package."
Apache Superset is a modern, enterprise-ready business intelligence web application
@@ -205,9 +205,9 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
| supersetCeleryBeat.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade |
| supersetCeleryBeat.initContainers | list | a container waiting for postgres | List of init containers |
| supersetCeleryBeat.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryBeat pods |
| supersetCeleryBeat.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetCeleryBeat pods |
| supersetCeleryBeat.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetCeleryBeat pods |
| supersetCeleryBeat.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetCeleryBeat.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryBeat.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryBeat.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryBeat.podLabels | object | `{}` | Labels to be added to supersetCeleryBeat pods |
@@ -231,9 +231,9 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
| supersetCeleryFlower.livenessProbe.successThreshold | int | `1` | |
| supersetCeleryFlower.livenessProbe.timeoutSeconds | int | `1` | |
| supersetCeleryFlower.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryFlower pods |
| supersetCeleryFlower.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetCeleryFlower pods |
| supersetCeleryFlower.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetCeleryFlower pods |
| supersetCeleryFlower.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetCeleryFlower.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryFlower.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryFlower.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetCeleryFlower.podLabels | object | `{}` | Labels to be added to supersetCeleryFlower pods |
@@ -285,10 +285,10 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
| supersetMcp.livenessProbe.successThreshold | int | `1` | |
| supersetMcp.livenessProbe.timeoutSeconds | int | `3` | |
| supersetMcp.podAnnotations | object | `{}` | Annotations to be added to supersetMcp pods |
| supersetMcp.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetMcp pods |
| supersetMcp.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetMcp pods |
| supersetMcp.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetMcp.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/\#specifying-a-poddisruptionbudget |
| supersetMcp.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/\#specifying-a-poddisruptionbudget |
| supersetMcp.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetMcp.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetMcp.podLabels | object | `{}` | Labels to be added to supersetMcp pods |
| supersetMcp.priorityClassName | string | `nil` | Set priorityClassName for supersetMcp pods |
@@ -341,9 +341,9 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
| supersetNode.livenessProbe.successThreshold | int | `1` | |
| supersetNode.livenessProbe.timeoutSeconds | int | `1` | |
| supersetNode.podAnnotations | object | `{}` | Annotations to be added to supersetNode pods |
| supersetNode.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetNode pods |
| supersetNode.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetNode pods |
| supersetNode.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetNode.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetNode.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetNode.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetNode.podLabels | object | `{}` | Labels to be added to supersetNode pods |
| supersetWebsockets.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetWebsockets pods |
| supersetWebsockets.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetWebsockets pods |
| supersetWebsockets.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetWebsockets.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetWebsockets.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetWebsockets.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
@@ -448,9 +448,9 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
| supersetWorker.livenessProbe.successThreshold | int | `1` | |
| supersetWorker.livenessProbe.timeoutSeconds | int | `60` | |
| supersetWorker.podAnnotations | object | `{}` | Annotations to be added to supersetWorker pods |
| supersetWorker.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":1,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetWorker pods |
| supersetWorker.podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":1}` | Sets the [pod disruption budget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for supersetWorker pods |
| supersetWorker.podDisruptionBudget.enabled | bool | `false` | Whether the pod disruption budget should be created |
| supersetWorker.podDisruptionBudget.maxUnavailable | int | `1` | If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetWorker.podDisruptionBudget.maxUnavailable | string | `nil` | If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetWorker.podDisruptionBudget.minAvailable | int | `1` | If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget |
| supersetWorker.podLabels | object | `{}` | Labels to be added to supersetWorker pods |
{{- with .Values.supersetCeleryFlower.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "supersetCeleryFlower.podDisruptionBudget: only one of minAvailable or maxUnavailable should be set - unset the other one (set it to null)" }}
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:~
# -- Startup command
# @default -- See `values.yaml`
@@ -542,8 +542,8 @@ supersetWorker:
enabled:false
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:~
# -- Worker startup command
# @default -- a `celery worker` command
command:
@@ -665,8 +665,8 @@ supersetCeleryBeat:
enabled:false
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:~
# -- Command
# @default -- a `celery beat` command
command:
@@ -751,8 +751,8 @@ supersetCeleryFlower:
enabled:false
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:~
# -- Command
# @default -- a `celery flower` command
command:
@@ -869,8 +869,8 @@ supersetWebsockets:
enabled:false
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
maxUnavailable:~
ingress:
path:/ws
pathType:Prefix
@@ -999,10 +999,10 @@ supersetMcp:
podDisruptionBudget:
# -- Whether the pod disruption budget should be created
enabled:false
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/\#specifying-a-poddisruptionbudget
# -- If set, maxUnavailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
minAvailable:1
# -- If set, minAvailable must not be set - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/\#specifying-a-poddisruptionbudget
maxUnavailable:1
# -- If set, minAvailable must be unset (`minAvailable: ~`) - see https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.