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
       ? [
           {

Reply via email to