Skip to content

Conversation

@michael-s-molina
Copy link
Member

SUMMARY

This PR adds a resolvePermalinkUrl callback to the Embedded SDK that allows host applications to customize the permalink URLs generated when users click share buttons inside an embedded dashboard.

Problem:
When users click "Copy Link" on a chart or dashboard inside an embedded Superset dashboard, the generated permalink uses Superset's domain (e.g., https://superset.example.com/superset/dashboard/p/xyz789/). Host applications often need full control over the permalink URL to use their own domain, paths, and query parameters.

Solution:

  • Added resolvePermalinkUrl callback to the SDK's embedDashboard() options
  • When a permalink is generated, Superset calls this callback with the permalink key
  • The host can return a custom URL (e.g., https://my-app.com/analytics/share/xyz789)
  • If no callback is provided, Superset's default URL is used (backward compatible)

Architecture:

User clicks "Copy Link" in embedded Superset
            ↓
    POST /api/v1/dashboard/{id}/permalink
            ↓
    Backend returns { key: "xyz789", url: "..." }
            ↓
    Switchboard.get('resolvePermalinkUrl', { key })  ──→  SDK
            ↓                                              ↓
            ↓                                    host.resolvePermalinkUrl({ key })
            ↓                                              ↓
            ←──────────────────────────────────  "https://my-app.com/share/xyz789"
            ↓
    Copy resolved URL to clipboard

Additional fix:

  • Fixed anchor scrolling for permalinks in embedded mode. The anchor (chart/tab ID to scroll to) was already stored in the permalink state but wasn't being applied when loading embedded dashboards. Now DashboardPage.tsx extracts the anchor from the permalink state and scrolls to the element after hydration.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A - This is an SDK API change, not a UI change.

TESTING INSTRUCTIONS

  1. Test custom permalink URLs in embedded mode:

    embedDashboard({
      id: "your-dashboard-uuid",
      supersetDomain: "https://superset.example.com",
      mountPoint: document.getElementById("dashboard"),
      fetchGuestToken: () => fetchGuestTokenFromBackend(),
      resolvePermalinkUrl: ({ key }) => {
        console.log("Permalink key:", key);
        return `https://my-app.com/share/${key}`;
      }
    });
    • Click the share/copy link button on a chart inside the embedded dashboard
    • Verify the clipboard contains your custom URL (e.g., https://my-app.com/share/xyz789)
  2. Test fallback behavior (no callback):

    • Remove the resolvePermalinkUrl callback
    • Click share/copy link
    • Verify Superset's default URL is used
  3. Test permalink restoration with anchor:

    embedDashboard({
      // ...
      dashboardUiConfig: {
        urlParams: {
          permalink_key: "xyz789"  // A permalink that was created from a specific chart
        }
      }
    });
    • Verify the dashboard loads with the correct filter state
    • Verify the page scrolls to the specific chart that was shared
  4. Test non-embedded mode still works:

    • Open a regular (non-embedded) dashboard
    • Click share/copy link on a chart
    • Verify the permalink URL is generated correctly

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • 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

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 6, 2026

Code Review Agent Run #0452f7

Actionable Suggestions - 0
Review Details
  • Files reviewed - 6 · Commit Range: 6cc5b57..6cc5b57
    • superset-embedded-sdk/src/index.ts
    • superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/index.tsx
    • superset-frontend/src/dashboard/containers/DashboardPage.tsx
    • superset-frontend/src/embedded/api.tsx
    • superset-frontend/src/utils/urlUtils.ts
  • Files skipped - 1
    • superset-embedded-sdk/README.md - Reason: Filter setting
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot bot added the api Related to the REST API label Jan 6, 2026
@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI finished reviewing your PR.

@github-actions github-actions bot removed the api Related to the REST API label Jan 6, 2026
@apache apache deleted a comment from codeant-ai-for-open-source bot Jan 6, 2026
@apache apache deleted a comment from codeant-ai-for-open-source bot Jan 6, 2026
@apache apache deleted a comment from netlify bot Jan 6, 2026
@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 6, 2026

Code Review Agent Run #c9a4e1

Actionable Suggestions - 0
Review Details
  • Files reviewed - 6 · Commit Range: 6cc5b57..42b9006
    • superset-embedded-sdk/src/index.ts
    • superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/index.tsx
    • superset-frontend/src/dashboard/containers/DashboardPage.tsx
    • superset-frontend/src/embedded/api.tsx
    • superset-frontend/src/utils/urlUtils.ts
  • Files skipped - 1
    • superset-embedded-sdk/README.md - Reason: Filter setting
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 6, 2026

Code Review Agent Run #d38128

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/src/explore/components/EmbedCodeContent.jsx - 1
    • Missing error handling for failed permalink URL · Line 47-52
      The change correctly updates the code to access `result.url` since `getChartPermalink` returns an object, but it lacks handling for cases where the API resolves without a `url` property. Without this, users might see 'Generating link, please wait..' indefinitely if the permalink API fails to include the URL. Consider adding error handling in an else block to set an error message and show a toast, similar to the catch block.
      Code suggestion
       @@ -47,6 +47,8 @@
      -      .then(result => {
      -        if (result?.url) {
      -          setUrl(result.url);
      -          setErrorMessage('');
      -        }
      -      })
      +      .then(result => {
      +        if (result?.url) {
      +          setUrl(result.url);
      +          setErrorMessage('');
      +        } else {
      +          setErrorMessage(t('Error'));
      +          addDangerToast(t('Sorry, something went wrong. Try again later.'));
      +        }
      +      })
Review Details
  • Files reviewed - 8 · Commit Range: 42b9006..0e855aa
    • superset-embedded-sdk/src/index.ts
    • superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/index.tsx
    • superset-frontend/src/dashboard/containers/DashboardPage.tsx
    • superset-frontend/src/embedded/api.tsx
    • superset-frontend/src/explore/components/EmbedCodeContent.jsx
    • superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx
    • superset-frontend/src/utils/urlUtils.ts
  • Files skipped - 1
    • superset-embedded-sdk/README.md - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@Vitor-Avila
Copy link
Contributor

Hey @michael-s-molina,

This is a very nice feature! Thanks for working on this. 🙌

I tried testing this locally, but it's not working properly for me, unsure if I'm missing something. Here's what I tried:

  1. Executed gh pr checkout 36924 to get your changes locally.
  2. Got npm ci && npm run dev-server in one terminal from superset-frontend, superset run -p 8088 --with-threads --reload --debugger in another, and npm run build && http-server -p 8000 from superset-embedded-sdk in another one.
  3. Loaded the embedded SDK with <script src="http://127.0.0.1:8000/bundle/index.js"></script>.
  4. Used the SDK with:
const myLightDashboard = supersetEmbeddedSdk.embedDashboard({
	id: dashboardId,
	supersetDomain: supersetDomain,
	mountPoint: document.getElementById("dashboard-container"),
	fetchGuestToken: async () => fetchGuestTokenFromBackend(),
	dashboardUiConfig: {
		hideTitle: false,
		hideChartControls: false,
	},
	resolvePermalinkUrl: ({ key }) => {
		return `https://my-app.com/analytics/share/${key}`;
	},
});

Everything loads fine, but the Share options still give me a http://localhost:8088/ URL. Am I missing something?

Also, while you're working on this, I wonder if you would want to re-add anchor links from tabs and headers in embedded dashboards? I removed them back here, as they don't really work for embedded users (you can't really use that link and shouldn't even have access to it). My only concern here would be how to make this configureable: as you can imagine, not all Embedded Orgs would want to display permalinks. The Share options can be hidden through perms (in case the Guest Role has permission to create permalink or not) but the anchor links for tabs/headers are not managed via perms. Some options:

  1. Have a new config to control if these should be visible in embedded or not.
    Pros: Flexibility to support both use-cases.
    Cons: Not as flexible as perms.
  2. Validate can share perms to determine if anchor links should be visible.
    Pros: Flexibility to support both use-cases. Also aligned with other Share buttons.
    Cons: Slightly bigger change.
  3. Keep as is (or re-add without validation)
    Pros: No flexibility.
    Cons: Easy to implement (either keep as-is or revert my PR).

Second option seems like the best move here. WDYT?

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@michael-s-molina
Copy link
Member Author

I tried testing this locally, but it's not working properly for me

@Vitor-Avila I fixed the bug and also added a way for consumers to configure iframe's allow property which is required for copy/paste and other operations.

Screen.Recording.2026-01-09.at.11.34.28.mov

@michael-s-molina
Copy link
Member Author

michael-s-molina commented Jan 9, 2026

you would want to re-add anchor links from tabs and headers in embedded dashboards?

@Vitor-Avila Let's handle this a follow-up PR given the parallel discussion regarding the options.

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 9, 2026

Code Review Agent Run #4be3b4

Actionable Suggestions - 0
Review Details
  • Files reviewed - 8 · Commit Range: 0e855aa..302a71f
    • superset-embedded-sdk/src/index.ts
    • superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/index.tsx
    • superset-frontend/src/dashboard/containers/DashboardPage.tsx
    • superset-frontend/src/embedded/api.tsx
    • superset-frontend/src/explore/components/EmbedCodeContent.jsx
    • superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx
    • superset-frontend/src/utils/urlUtils.ts
  • Files skipped - 1
    • superset-embedded-sdk/README.md - Reason: Filter setting
  • Tools
    • 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 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Copy link
Member

@justinpark justinpark left a comment

Choose a reason for hiding this comment

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

LGTM

@michael-s-molina michael-s-molina merged commit 53dddf4 into apache:master Jan 9, 2026
70 checks passed
@Vitor-Avila
Copy link
Contributor

@michael-s-molina thanks for fixing this flow. I agree we can tackle that in a follow up. Another thing I noticed is that while I can get the permalink key, using it via urlParams doesn't "scroll" to the chart. Def another thing for a follow up (as that's not the primary goal of this PR) but thought I would mention in case you're planning on using this.

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.

3 participants