Skip to content

fix(frontend): use SupersetClient in ImageLoader to prepend SUPERSET_APP_ROOT - #45640

Open
greg-om wants to merge 4 commits into
apache:masterfrom
greg-om:fix/imageloader-app-root
Open

greg-om wants to merge 4 commits into
apache:masterfrom
greg-om:fix/imageloader-app-root

Conversation

@greg-om

@greg-om greg-om commented Oct 22, 2026 •

Copy link
Copy Markdown

ImageLoader fetched thumbnails with a bare fetch, so root-relative thumbnail_url paths didn't prepend SUPERSET_APP_ROOT. Moved the ListViewCard story images to imgFallbackURL since Storybook has no configured client.

SUMMARY

When Superset is served under a subdirectory i.e. (SUPERSET_APP_ROOT=/analytics), thumbnails on the chart list, the dashboard list and the dashboard editor's "add chart" panel are requested without the prefix: the page asks for /api/v1/chart/123/thumbnail/<digest>/ instead of /analytics/api/v1/chart/123/thumbnail/<digest>/.

Root cause. ImageLoader (packages/superset-ui-core/src/components/ListViewCard/ImageLoader.tsx) loads images with a bare fetch(src). The backend's thumbnail_url is a root-relative API path without the app root, which matches the frontend convention since #39925, so the prefix has to be added client side. A bare fetch never goes through SupersetClient.getUrl, so it never gets it.

Fix. ImageLoader requests src through SupersetClient.get({ endpoint: src, parseMethod: 'raw' }), the same pattern used in useDownloadScreenshot.ts and utils/export.ts. The client adds the app root, the CSRF header and the auth handling. Callers (ChartCard, DashboardCard, AddSliceCard) are unchanged.

Behaviour changes

  • ImageLoader's src must be a Superset endpoint. Absolute external URLs are no longer supported; no caller in the app passes one.
  • A 401 on a thumbnail triggers SupersetClient's redirect to login, like any other API call.
  • The request waits for ensureAuth(), so it starts asynchronously rather than during the first effect run.

Stories and docs. The ListViewCard stories passed picsum URLs as imgURL. Storybook and the docs portal never configure SupersetClient, so those stories would throw. The picsum images move to imgFallbackURL (a CSS background, not fetched) and imgURL is empty. docs/developer_docs/components/ui/listviewcard.mdx is regenerated from the stories. Typing an endpoint into the imgURL control in Storybook or the docs page will still fail, since there is no configured client there.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A. With SUPERSET_APP_ROOT set, list cards go from the placeholder image to the real thumbnail. Without an app root, nothing changes.

TESTING INSTRUCTIONS

Automated:

cd superset-frontend
npm run test -- packages/superset-ui-core/src/components/ListViewCard

Manual:

  1. Enable the THUMBNAILS feature flag and a working thumbnail cache/worker setup.
  2. Serve Superset under a subdirectory, e.g. SUPERSET_APP_ROOT=/analytics, behind a proxy that only routes /analytics to Superset.
  3. Open the chart list and dashboard list in card view, and the "add chart" panel in dashboard edit mode.
  4. In the network tab, thumbnail requests go to /analytics/api/v1/.../thumbnail/... and the images render. On master they go to /api/v1/... and fall back to the placeholder.
  5. Without SUPERSET_APP_ROOT, thumbnails load as before.

ADDITIONAL INFORMATION

  • Has associated issue: Fixes Chart and dashboard thumbnails ignore SUPERSET_APP_ROOT #45638
  • Required feature flags: THUMBNAILS (to see thumbnails at all)
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

…APP_ROOT

ImageLoader fetched thumbnails with a bare fetch, so root-relative thumbnail_url paths didn't prepend SUPERSET_APP_ROOT.  Moved the ListViewCard story images to imgFallbackURL since Storybook has no configured client.
@codeant-ai-for-open-source

codeant-ai-for-open-source Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

CodeAnt  CodeAnt PR Risk

🟢  Low Risk

  • The PR appears safe to merge; no actionable issues were identified in the review.

Assessed commit: bf5b953f91e1

useEffect(() => {
if (src) {
fetch(src)
SupersetClient.get({ endpoint: src, parseMethod: 'raw' })

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Switching to SupersetClient.get changes the fetch call that the callers' tests assert on: SupersetClient awaits ensureAuth() and then calls fetch with an absolute URL and an options object. DashboardCard.test.tsx (thumbnail URL construction, around lines 226-257) still expects a synchronous fetch('/api/v1/dashboard/<id>/thumbnail/<ts>/') with no second argument, and the sharded-jest-tests (2) check fails on exactly those two assertions. Could you update them to wait for the request and match the new fetch signature (or assert on SupersetClient.get)?

ImageLoader fetches thumbnails via SupersetClient.get, which awaits ensureAuth() before fetch. Test now waits for the request and matches the URL by its path and method option
@netlify

netlify Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit e5fab90
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6ae283a7f716f0719dfd81e5
😎 Deploy Preview https://deploy-preview-45640--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.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Translation Regression Detected

A source change in this PR renamed or reworded strings, invalidating existing translations (they are now #, fuzzy) in tr. Please resolve the affected .po files before merging.

Note: neither intentionally deleting a translatable string nor filling a previously-untranslated entry with a fuzzy guess (e.g. an AI backfill) is a regression — only a confirmed translation that a renamed/reworded source string turned fuzzy is flagged here.

Language Invalidated translations
tr 196

How to fix

1. Install dependencies (if not already set up):

pip install -r superset/translations/requirements.txt
sudo apt-get install gettext   # or: brew install gettext

2. Re-extract strings and sync .po files:

./scripts/translations/babel_update.sh

This rewrites superset/translations/messages.pot from the current source files and merges the changes into every .po file. Strings whose msgid changed will be marked #, fuzzy.

3. Resolve the fuzzy entries in the affected language files (tr):

grep -n '#, fuzzy' superset/translations/<lang>/LC_MESSAGES/messages.po

For each fuzzy entry, either rewrite the msgstr to match the new string and remove the #, fuzzy line, or clear the msgstr to "" if you cannot provide a translation.

4. Commit your changes to the .po files.

@codecov

codecov Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.62%. Comparing base (0a92706) to head (bf5b953).
⚠️ Report is 60 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #45640   +/-   ##
=======================================
  Coverage   84.62%   84.62%           
=======================================
  Files        3069     3069           
  Lines      205483   205483           
  Branches    48295    48295           
=======================================
+ Hits       173882   173883    +1     
+ Misses      28307    28306    -1     
  Partials     3294     3294           
Flag Coverage Δ
javascript 80.77% <100.00%> (+<0.01%) ⬆️

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.

useEffect(() => {
if (src) {
fetch(src)
SupersetClient.get({ endpoint: src, parseMethod: 'raw' })

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

SupersetClient.get calls getInstance(), which throws synchronously when configure() was never called, so the error skips the .catch below and the effect throws on mount instead of showing the fallback image. Storybook and the docs portal never configure the client, and docs/developer_docs/components/ui/listviewcard.mdx at this head still passes imgURL="https://picsum.photos/seed/superset/300/200" (lines 39 and 100), so that live example would crash rather than render. Could the request be started inside the promise chain (for example Promise.resolve().then(() => SupersetClient.get(...))) so an unconfigured client falls back to imgFallbackURL?

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chart and dashboard thumbnails ignore SUPERSET_APP_ROOT

2 participants