Skip to content

feat(standalone): granular Explore standalone modes and iframe-safe dashboard fullscreen - #44165

Open
anamitraadhikari wants to merge 2 commits into
apache:masterfrom
anamitraadhikari:aadhikari/standalone-embed-fixes
Open

feat(standalone): granular Explore standalone modes and iframe-safe dashboard fullscreen#44165
anamitraadhikari wants to merge 2 commits into
apache:masterfrom
anamitraadhikari:aadhikari/standalone-embed-fixes

Conversation

@anamitraadhikari

@anamitraadhikari anamitraadhikari commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Description:

SUMMARY

Adds a second Explore standalone mode and makes the dashboard fullscreen
toggle safe to use inside an iframe.

standalone on Explore was previously all-or-nothing: any truthy value
rendered a bare chart. Embedding an editable chart in an iframe therefore
meant choosing between "no chart controls at all" and "the full Superset
nav". This adds ExploreStandaloneMode:

  • 1 — chart only (unchanged; what thumbnails and screenshots use)
  • 2 — hide the nav, keep the editor controls

Because the bootstrap payload only carries is_standalone_mode(), a
boolean, the mode is resolved from the URL via getUrlParam, which already
maps '1'/'true' to 1 and '2' to 2. Screenshot URLs
(ChartStandaloneMode.HIDE_NAV sends standalone=true) keep working.
mountExploreUrl now carries the active mode through extraSearch instead
of writing standalone=1 unconditionally, which would otherwise downgrade
mode 2 to mode 1 on the first history.replace.

On dashboards, the header's fullscreen toggle is hidden when the page is
actually inside an iframe (isEmbedded() from dashboard/util/isEmbedded).
Exiting fullscreen reloads without the standalone param and restores the
full Superset nav, which breaks an embed. Note this is distinct from the
isEmbedded local in the menu hook, which is !dashboardInfo.userId and
only covers anonymous guests via the embedded SDK — not an authenticated
user whose dashboard is iframed. Top-level users keep both directions, so
fullscreen is not a one-way door.

No Python behaviour changes: is_standalone_mode() is untouched and still
returns a boolean. The only backend edit is one added enum value on
ChartStandaloneMode.

BEFORE/AFTER SCREENSHOTS

Screenshot 1:
Explore with standalone=2 (new mode): Superset nav hidden, chart editor controls kept. On master any truthy standalone renders a bare chart, so this layout was not previously possible.
Screenshot 2026-09-11 at 10 10 15 AM

Screenshot 2:
Dashboard inside an iframe with standalone=1: the ⋮ menu offers no fullscreen toggle. Exiting would reload without standalone and restore the full Superset nav, breaking the embed. Outside an iframe the menu is unchanged.
Screenshot 2026-09-11 at 10 01 47 AM

TESTING INSTRUCTIONS

Explore:

  • /explore/?slice_id=<id> — full editor with nav
  • /explore/?slice_id=<id>&standalone=1 — chart only
  • /explore/?slice_id=<id>&standalone=2 — no nav, editor controls kept
  • /explore/?slice_id=<id>&standalone=true — chart only (screenshot path)
  • In mode 2, interact with the chart; the editor must not collapse to a
    bare chart

Dashboard:

  • /superset/dashboard/<id>/ — "Enter fullscreen" present in the ⋮ menu
  • Click it — URL gains standalone=1 and "Exit fullscreen" is available
  • Load the same URL inside an iframe — no fullscreen item at all

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration
  • Introduces new feature or API
  • Removes existing feature or API

aadhikari added 2 commits August 28, 2026 17:33
…in standalone dashboards

- Add ExploreStandaloneMode enum: 1=chart-only (backward compat), 2=hide nav but keep editor controls
- Hide "Enter fullscreen" menu item when dashboard is already in standalone mode
- Update ExploreViewContainer and ExploreChartPanel to use numeric standalone instead of boolean
- Add backend ChartStandaloneMode.HIDE_NAV_SHOW_CONTROLS enum value
- Add tests for both standalone modes
- Fix PropTypes: standalone bool → number
…escapable

The granular standalone work in the previous commit switched the Explore
frontend to a numeric comparison, but three things it depends on still
assumed the old boolean, single-mode world.

Explore ignored the mode. The bootstrap payload carries
`is_standalone_mode()`, a boolean, so `standalone === HideNav` was never
true and `standalone=1` rendered the full editor instead of a bare chart.
Mode 2 only appeared to work because the full editor is also its intended
output. The mode is now read from the URL with `getUrlParam`, which already
maps '1'/'true' to 1 and '2' to 2, so screenshot URLs
(`ChartStandaloneMode.HIDE_NAV` sends `standalone=true`) keep working. The
redux and bootstrap types go back to `boolean` to match what the backend
actually sends.

Mode 2 collapsed to mode 1 on any interaction. `mountExploreUrl` wrote
`standalone=1` unconditionally, and Explore calls it on `history.replace`
after interactions, so the editor turned into a bare chart on the first
click. Callers now pass the active mode through `extraSearch` and the util
only supplies HideNav when nothing was given.

Fullscreen became a one-way door. The dashboard header hid the toggle
whenever `standalone` was set, but that param is also what "Enter
fullscreen" sets, so the menu item removed its own escape hatch. The guard
is now a real iframe check via `isEmbedded()`, which is what the embed
protection was reaching for -- the existing `isEmbedded` local is
`!dashboardInfo.userId` and does not cover an authenticated user in an
iframe. Top-level users keep both directions; iframes get no toggle at all.

No Python changes: `is_standalone_mode()` stays boolean and is untouched.

Tests: URL-driven Explore cases for modes 1, 2 and 'true'; an iframe case
for the dashboard menu; mode-preservation tests for `mountExploreUrl`; and
the subdirectory-prefix "Exit fullscreen" test is restored now that the
exit path is reachable again.
@netlify

netlify Bot commented Sep 11, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit a9416cf
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6aa3b6f145c9ef0008dd0442
😎 Deploy Preview https://deploy-preview-44165--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 79.74%. Comparing base (30402b4) to head (a9416cf).
⚠️ Report is 354 commits behind head on master.

Files with missing lines Patch % Lines
superset/utils/webdriver.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44165      +/-   ##
==========================================
+ Coverage   79.21%   79.74%   +0.52%     
==========================================
  Files        2879     2899      +20     
  Lines      166040   170334    +4294     
  Branches    38405    39149     +744     
==========================================
+ Hits       131536   135835    +4299     
+ Misses      32025    31902     -123     
- Partials     2479     2597     +118     
Flag Coverage Δ
hive 37.34% <0.00%> (-0.60%) ⬇️
mysql 56.86% <0.00%> (-0.81%) ⬇️
postgres 56.89% <0.00%> (-0.82%) ⬇️
presto 39.22% <0.00%> (-0.62%) ⬇️
python 84.55% <0.00%> (+0.80%) ⬆️
sqlite 56.59% <0.00%> (-0.81%) ⬇️
unit 75.87% <0.00%> (+1.90%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bito-code-review bito-code-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #97acfd

Actionable Suggestions - 1
  • superset-frontend/src/explore/components/ExploreChartPanel/index.tsx - 1
Additional Suggestions - 6
  • superset-frontend/src/explore/components/ExploreViewContainer/index.tsx - 1
    • Redundant standalone spread · Line 252-252
      This spread is dead: `...additionalParam` is spread after it, and `additionalParam` (from `history.location.search`) always contains `standalone` whenever `standalone` is truthy, since `props.standalone` is derived from the same URL via `getUrlParam`. The numeric value is always overridden by the URL string, so mode 2 is already carried by `additionalParam`. Remove the line or move it after `...additionalParam` if the numeric mode must win.
  • superset/utils/webdriver.py - 1
    • Dead enum member · Line 141-141
      `HIDE_NAV_SHOW_CONTROLS = 2` is added to `ChartStandaloneMode` but never referenced in any Python file. The only backend consumer, `superset/utils/screenshots.py:490`, uses `ChartStandaloneMode.HIDE_NAV.value`, and `ReservedUrlParameters.is_standalone_mode()` treats standalone as a boolean. The frontend `ExploreStandaloneMode.HideNavShowControls` is used, but this backend member is dead code. Remove it or consume it.
  • superset-frontend/src/explore/constants.ts - 1
    • Unused enum member · Line 229-229
      `HideNavShowControls` (=2) is never referenced anywhere in the codebase; consumers only special-case `ExploreStandaloneMode.HideNav` (=1), so mode 2 relies on implicit fall-through to the full editor. Either drop the member or branch on it explicitly in `ExploreViewContainer`/`ExploreChartPanel` so mode 2's behavior is intentional.
  • superset-frontend/src/explore/components/ExploreViewContainer/ExploreViewContainer.test.tsx - 2
    • Magic number in mock · Line 135-135
      The mock hardcodes `standalone === 1`, but production (`ExploreChartPanel/index.tsx:507`) compares against `ExploreStandaloneMode.HideNav`. If the enum value ever changes, this test silently diverges from real behavior. Import `ExploreStandaloneMode` from 'src/explore/constants' and compare `standalone === ExploreStandaloneMode.HideNav` instead of the literal `1`.
    • Wrong enum in comment · Line 299-299
      The comment references `ChartStandaloneMode.HIDE_NAV`, but no such enum exists in the repo — the actual enum is `ExploreStandaloneMode.HideNav` (constants.ts:226). This misleads readers about the mode's source. Update the comment to the real symbol.
  • superset-frontend/src/dashboard/components/Header/Header.test.tsx - 1
    • Test mock inconsistency · Line 874-880
      This test simulates "not in standalone mode" via `window.history.pushState('/dashboard')`, but the `useLocation` mock (line 51) still hardcodes `search: '?standalone=1'`. The label logic in `useHeaderActionsDropdownMenu` reads `getUrlParam(URL_PARAMS.standalone)` (i.e. `window.location.search`), so the test passes today — but the mock contradicts the scenario, and a refactor to `location.search` would silently break it.
Review Details
  • Files reviewed - 10 · Commit Range: d2a1dcd..a9416cf
    • superset-frontend/src/dashboard/components/Header/Header.test.tsx
    • superset-frontend/src/dashboard/components/Header/useHeaderActionsDropdownMenu.tsx
    • superset-frontend/src/explore/components/ExploreChartPanel/index.tsx
    • superset-frontend/src/explore/components/ExploreViewContainer/ExploreViewContainer.test.tsx
    • superset-frontend/src/explore/components/ExploreViewContainer/index.tsx
    • superset-frontend/src/explore/constants.ts
    • superset-frontend/src/explore/exploreUtils/exploreUtils.test.tsx
    • superset-frontend/src/explore/exploreUtils/index.ts
    • superset-frontend/src/explore/types.ts
    • superset/utils/webdriver.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

);

if (standalone) {
if (standalone === ExploreStandaloneMode.HideNav) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test regression from strict equality

standalone is now compared with strict equality (=== ExploreStandaloneMode.HideNav, i.e. === 1). The existing ExploreChartPanel.test.tsx passes standalone: true (boolean), and true === 1 is false, so the standalone branch no longer renders StandaloneDownloadControl and the test at line 232 will fail. Update those tests to pass the numeric mode.

Code Review Run #97acfd


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant