You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by di...@apache.org on 2024/09/10 17:27:26 UTC

(superset) branch master updated: fix(Dashboard download): Download dashboard screenshot/PDF using SupersetClient (#30212)

This is an automated email from the ASF dual-hosted git repository.

diegopucci pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new d191e67e51 fix(Dashboard download): Download dashboard screenshot/PDF using SupersetClient (#30212)
d191e67e51 is described below

commit d191e67e519cf3867a45f833adec34e8e6ad276c
Author: Vitor Avila <96...@users.noreply.github.com>
AuthorDate: Tue Sep 10 14:27:19 2024 -0300

    fix(Dashboard download): Download dashboard screenshot/PDF using SupersetClient (#30212)
---
 .../DownloadMenuItems/DownloadScreenshot.test.tsx  | 47 +++++++++++++---------
 .../menu/DownloadMenuItems/DownloadScreenshot.tsx  | 41 +++++++++++--------
 2 files changed, 54 insertions(+), 34 deletions(-)

diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx
index 21bd7022eb..01d756403a 100644
--- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx
+++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx
@@ -84,7 +84,7 @@ describe('DownloadScreenshot component', () => {
     const props = defaultProps();
 
     fetchMock.post(
-      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot`,
+      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot/`,
       {
         status: 400,
         body: {},
@@ -105,19 +105,23 @@ describe('DownloadScreenshot component', () => {
   test('displays success message when API call succeeds', async () => {
     const props = defaultProps();
     fetchMock.post(
-      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot`,
+      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot/`,
       {
         status: 200,
         body: {
           image_url: 'mocked_image_url',
+          cache_key: 'mocked_cache_key',
         },
       },
     );
 
-    fetchMock.get('glob:*/mocked_image_url?download_format=pdf', {
-      status: 200,
-      body: {},
-    });
+    fetchMock.get(
+      `glob:*/api/v1/dashboard/${props.dashboardId}/screenshot/mocked_cache_key/?download_format=pdf`,
+      {
+        status: 200,
+        body: {},
+      },
+    );
 
     renderComponent();
 
@@ -130,14 +134,14 @@ describe('DownloadScreenshot component', () => {
     });
   });
 
-  test('throws error when no image URL is provided', async () => {
+  test('throws error when no image cache key is provided', async () => {
     const props = defaultProps();
     fetchMock.post(
-      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot`,
+      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot/`,
       {
         status: 200,
         body: {
-          image_url: '',
+          cache_key: '',
         },
       },
     );
@@ -156,24 +160,27 @@ describe('DownloadScreenshot component', () => {
 
   test('displays success message when image retrieval succeeds', async () => {
     const props = defaultProps();
-    const imageUrl = 'glob:*/mocked_image_url?download_format=pdf';
     fetchMock.post(
-      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot`,
+      `glob:*/api/v1/dashboard/${props.dashboardId}/cache_dashboard_screenshot/`,
       {
         status: 200,
         body: {
           image_url: 'mocked_image_url',
+          cache_key: 'mocked_cache_key',
         },
       },
     );
 
-    fetchMock.get(imageUrl, {
-      status: 200,
-      headers: {
-        'Content-Type': 'image/png',
+    fetchMock.get(
+      `glob:*/api/v1/dashboard/${props.dashboardId}/screenshot/mocked_cache_key/?download_format=pdf`,
+      {
+        status: 200,
+        headers: {
+          'Content-Type': 'application/pdf',
+        },
+        body: new Blob([], { type: 'application/pdf' }),
       },
-      body: new Blob([], { type: 'image/png' }),
-    });
+    );
 
     global.URL.createObjectURL = jest.fn(() => 'mockedObjectURL');
     global.URL.revokeObjectURL = jest.fn();
@@ -185,7 +192,11 @@ describe('DownloadScreenshot component', () => {
     userEvent.click(screen.getByRole('button', { name: 'Download' }));
 
     await waitFor(() => {
-      expect(fetchMock.calls(imageUrl).length).toBe(1);
+      expect(
+        fetchMock.calls(
+          `glob:*/api/v1/dashboard/${props.dashboardId}/screenshot/mocked_cache_key/?download_format=pdf`,
+        ).length,
+      ).toBe(1);
     });
 
     // Wait for the successful image retrieval message
diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx
index 361f9880fe..2d182e31fc 100644
--- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx
+++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx
@@ -17,7 +17,12 @@
  * under the License.
  */
 
-import { logging, t, SupersetClient } from '@superset-ui/core';
+import {
+  logging,
+  t,
+  SupersetClient,
+  SupersetApiError,
+} from '@superset-ui/core';
 import { Menu } from 'src/components/Menu';
 import {
   LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE,
@@ -63,14 +68,13 @@ export default function DownloadScreenshot({
     let retries = 0;
 
     // this function checks if the image is ready
-    const checkImageReady = (imageUrl: string) =>
-      fetch(`${imageUrl}?download_format=${format}`)
-        .then(response => {
-          if (response.status === 404) {
-            throw new Error('Image not ready');
-          }
-          return response.blob();
-        })
+    const checkImageReady = (cacheKey: string) =>
+      SupersetClient.get({
+        endpoint: `/api/v1/dashboard/${dashboardId}/screenshot/${cacheKey}/?download_format=${format}`,
+        headers: { Accept: 'application/pdf, image/png' },
+        parseMethod: 'raw',
+      })
+        .then((response: Response) => response.blob())
         .then(blob => {
           const url = window.URL.createObjectURL(blob);
           const a = document.createElement('a');
@@ -80,11 +84,16 @@ export default function DownloadScreenshot({
           a.click();
           document.body.removeChild(a);
           window.URL.revokeObjectURL(url);
+        })
+        .catch(err => {
+          if ((err as SupersetApiError).status === 404) {
+            throw new Error('Image not ready');
+          }
         });
 
     // this is the functions that handles the retries
-    const fetchImageWithRetry = (imageUrl: string) => {
-      checkImageReady(imageUrl)
+    const fetchImageWithRetry = (cacheKey: string) => {
+      checkImageReady(cacheKey)
         .then(() => {
           addSuccessToast(t('The screenshot is now being downloaded.'));
         })
@@ -100,7 +109,7 @@ export default function DownloadScreenshot({
                 noDuplicate: true,
               },
             );
-            setTimeout(() => fetchImageWithRetry(imageUrl), RETRY_INTERVAL);
+            setTimeout(() => fetchImageWithRetry(cacheKey), RETRY_INTERVAL);
           } else {
             addDangerToast(
               t(
@@ -113,7 +122,7 @@ export default function DownloadScreenshot({
     };
 
     SupersetClient.post({
-      endpoint: `/api/v1/dashboard/${dashboardId}/cache_dashboard_screenshot`,
+      endpoint: `/api/v1/dashboard/${dashboardId}/cache_dashboard_screenshot/`,
       jsonPayload: {
         anchor,
         activeTabs,
@@ -121,8 +130,8 @@ export default function DownloadScreenshot({
       },
     })
       .then(({ json }) => {
-        const imageUrl = json?.image_url;
-        if (!imageUrl) {
+        const cacheKey = json?.cache_key;
+        if (!cacheKey) {
           throw new Error('No image URL in response');
         }
         addInfoToast(
@@ -130,7 +139,7 @@ export default function DownloadScreenshot({
             'The screenshot is being generated. Please, do not leave the page.',
           ),
         );
-        fetchImageWithRetry(imageUrl);
+        fetchImageWithRetry(cacheKey);
       })
       .catch(error => {
         logging.error(error);