This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch live-edits in repository https://gitbox.apache.org/repos/asf/superset.git
commit 1c1d3b542f08308bfa751c7fc2e7a57d8ecaa54d Author: Evan Rusackas <[email protected]> AuthorDate: Thu Jan 8 19:20:49 2026 -0800 fix(dashboard): add email permalink and fix edit title timing - Add 'Share permalink by email' option to tab menu - Delay edit title trigger to allow menu to close first 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]> --- .../components/gridComponents/Tab/TabMenu.tsx | 52 +++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tab/TabMenu.tsx b/superset-frontend/src/dashboard/components/gridComponents/Tab/TabMenu.tsx index c27502edc40..20d5c2ca1e7 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tab/TabMenu.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tab/TabMenu.tsx @@ -91,6 +91,43 @@ export default function TabMenu({ addDangerToast, ]); + const handleEmailPermalink = useCallback(async () => { + try { + const includeChartState = + hasStatefulCharts(sliceEntities) && + chartStates && + Object.keys(chartStates).length > 0; + + const url = await getDashboardPermalink({ + dashboardId, + dataMask, + activeTabs, + anchor: tabId, + chartStates: includeChartState ? chartStates : undefined, + includeChartState, + }); + + const emailSubject = t('Superset dashboard '); + const emailBody = `${t('Check out this tab in dashboard:')} ${url}`; + window.location.href = `mailto:?Subject=${encodeURIComponent(emailSubject)}&Body=${encodeURIComponent(emailBody)}`; + } catch (error) { + if (error) { + addDangerToast( + (await getClientErrorObject(error)).error || + t('Something went wrong.'), + ); + } + } + }, [ + dashboardId, + tabId, + dataMask, + activeTabs, + chartStates, + sliceEntities, + addDangerToast, + ]); + const handleMenuClick: MenuProps['onClick'] = useCallback( ({ key, domEvent }) => { domEvent.stopPropagation(); @@ -100,14 +137,20 @@ export default function TabMenu({ case 'copy-permalink': handleCopyPermalink(); break; + case 'email-permalink': + handleEmailPermalink(); + break; case 'edit-title': - onEditTitle?.(); + // Delay to allow menu to close first + setTimeout(() => { + onEditTitle?.(); + }, 0); break; default: break; } }, - [handleCopyPermalink, onEditTitle], + [handleCopyPermalink, handleEmailPermalink, onEditTitle], ); const menuItems: MenuProps['items'] = [ @@ -116,6 +159,11 @@ export default function TabMenu({ label: t('Copy permalink'), icon: <Icons.LinkOutlined iconSize="m" />, }, + { + key: 'email-permalink', + label: t('Share permalink by email'), + icon: <Icons.MailOutlined iconSize="m" />, + }, ...(canEditDashboard ? [ {
