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

beto pushed a commit to branch file-handler2
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 14db9e0e8c8a6ae8d6b97162fed8f4daad880012
Author: Beto Dealmeida <[email protected]>
AuthorDate: Mon Dec 15 17:16:28 2025 -0500

    fix: PWA file handler installation and routing issues
    
    - Change route from /file-handler to /superset/file-handler to match Flask 
blueprint
    - Add Service-Worker-Allowed header for root scope registration
    - Add proper square icons (192x192, 512x512) for PWA install
    - Add wide and narrow screenshots for PWA install prompt
    - Update tests to use new route path
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude Opus 4.5 <[email protected]>
---
 .../src/assets/images/pwa/icon-192.png             | Bin 0 -> 1378 bytes
 .../src/assets/images/pwa/icon-512.png             | Bin 0 -> 4384 bytes
 .../src/assets/images/pwa/screenshot-narrow.png    | Bin 0 -> 100187 bytes
 .../src/assets/images/pwa/screenshot-wide.png      | Bin 0 -> 253025 bytes
 .../src/pages/FileHandler/index.test.tsx           |  44 ++++++++++-----------
 superset-frontend/src/pwa-manifest.json            |  40 +++++++++++++++++--
 superset-frontend/src/views/routes.tsx             |   2 +-
 superset/initialization/__init__.py                |   7 +++-
 8 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/superset-frontend/src/assets/images/pwa/icon-192.png 
b/superset-frontend/src/assets/images/pwa/icon-192.png
new file mode 100644
index 0000000000..a53fbe7e7b
Binary files /dev/null and 
b/superset-frontend/src/assets/images/pwa/icon-192.png differ
diff --git a/superset-frontend/src/assets/images/pwa/icon-512.png 
b/superset-frontend/src/assets/images/pwa/icon-512.png
new file mode 100644
index 0000000000..320eeb6382
Binary files /dev/null and 
b/superset-frontend/src/assets/images/pwa/icon-512.png differ
diff --git a/superset-frontend/src/assets/images/pwa/screenshot-narrow.png 
b/superset-frontend/src/assets/images/pwa/screenshot-narrow.png
new file mode 100644
index 0000000000..f601594e96
Binary files /dev/null and 
b/superset-frontend/src/assets/images/pwa/screenshot-narrow.png differ
diff --git a/superset-frontend/src/assets/images/pwa/screenshot-wide.png 
b/superset-frontend/src/assets/images/pwa/screenshot-wide.png
new file mode 100644
index 0000000000..c2a3731a0e
Binary files /dev/null and 
b/superset-frontend/src/assets/images/pwa/screenshot-wide.png differ
diff --git a/superset-frontend/src/pages/FileHandler/index.test.tsx 
b/superset-frontend/src/pages/FileHandler/index.test.tsx
index 4d99471a69..b8385f1712 100644
--- a/superset-frontend/src/pages/FileHandler/index.test.tsx
+++ b/superset-frontend/src/pages/FileHandler/index.test.tsx
@@ -134,8 +134,8 @@ beforeEach(() => {
 
 test('shows error when launchQueue is not supported', async () => {
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -154,8 +154,8 @@ test('redirects when no files are provided', async () => {
   const { triggerConsumer } = setupLaunchQueue();
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -175,8 +175,8 @@ test('handles CSV file correctly', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -196,8 +196,8 @@ test('handles Excel (.xls) file correctly', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -215,8 +215,8 @@ test('handles Excel (.xlsx) file correctly', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -234,8 +234,8 @@ test('handles Parquet file correctly', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -252,8 +252,8 @@ test('shows error for unsupported file type', async () => {
   const { triggerConsumer } = setupLaunchQueue();
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -277,8 +277,8 @@ test('handles file with uppercase extension', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -294,8 +294,8 @@ test('handles errors during file processing', async () => {
   const { triggerConsumer } = setupLaunchQueue();
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -324,8 +324,8 @@ test('modal close redirects to welcome page', async () => {
   setupLaunchQueue(fileHandle);
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
@@ -348,8 +348,8 @@ test('shows loading state while waiting for file', () => {
   setupLaunchQueue();
 
   render(
-    <MemoryRouter initialEntries={['/file-handler']}>
-      <Route path="/file-handler">
+    <MemoryRouter initialEntries={['/superset/file-handler']}>
+      <Route path="/superset/file-handler">
         <FileHandler />
       </Route>
     </MemoryRouter>,
diff --git a/superset-frontend/src/pwa-manifest.json 
b/superset-frontend/src/pwa-manifest.json
index 8b8755e189..fcd8f2213e 100644
--- a/superset-frontend/src/pwa-manifest.json
+++ b/superset-frontend/src/pwa-manifest.json
@@ -9,15 +9,49 @@
   "theme_color": "#20a7c9",
   "icons": [
     {
-      "src": "/static/assets/images/superset-logo-horiz.png",
-      "sizes": "any",
+      "src": "/static/assets/images/pwa/icon-192.png",
+      "sizes": "192x192",
       "type": "image/png",
       "purpose": "any"
+    },
+    {
+      "src": "/static/assets/images/pwa/icon-512.png",
+      "sizes": "512x512",
+      "type": "image/png",
+      "purpose": "any"
+    },
+    {
+      "src": "/static/assets/images/pwa/icon-192.png",
+      "sizes": "192x192",
+      "type": "image/png",
+      "purpose": "maskable"
+    },
+    {
+      "src": "/static/assets/images/pwa/icon-512.png",
+      "sizes": "512x512",
+      "type": "image/png",
+      "purpose": "maskable"
+    }
+  ],
+  "screenshots": [
+    {
+      "src": "/static/assets/images/pwa/screenshot-wide.png",
+      "sizes": "1280x720",
+      "type": "image/png",
+      "form_factor": "wide",
+      "label": "Apache Superset Dashboard"
+    },
+    {
+      "src": "/static/assets/images/pwa/screenshot-narrow.png",
+      "sizes": "540x720",
+      "type": "image/png",
+      "form_factor": "narrow",
+      "label": "Apache Superset Mobile View"
     }
   ],
   "file_handlers": [
     {
-      "action": "/file-handler",
+      "action": "/superset/file-handler",
       "accept": {
         "text/csv": [".csv"],
         "application/vnd.ms-excel": [".xls"],
diff --git a/superset-frontend/src/views/routes.tsx 
b/superset-frontend/src/views/routes.tsx
index eb6dbd05dd..87d38f7680 100644
--- a/superset-frontend/src/views/routes.tsx
+++ b/superset-frontend/src/views/routes.tsx
@@ -211,7 +211,7 @@ export const routes: Routes = [
     Component: Home,
   },
   {
-    path: '/file-handler',
+    path: '/superset/file-handler',
     Component: FileHandler,
   },
   {
diff --git a/superset/initialization/__init__.py 
b/superset/initialization/__init__.py
index 40801225b3..206fd4e5ca 100644
--- a/superset/initialization/__init__.py
+++ b/superset/initialization/__init__.py
@@ -648,7 +648,7 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
 
     def register_request_handlers(self) -> None:
         """Register app-level request handlers"""
-        from flask import Response
+        from flask import request, Response
 
         @self.superset_app.after_request
         def apply_http_headers(response: Response) -> Response:
@@ -664,6 +664,11 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
             for k, v in 
self.superset_app.config["DEFAULT_HTTP_HEADERS"].items():
                 if k not in response.headers:
                     response.headers[k] = v
+
+            # Allow service worker to control the root scope for PWA file 
handling
+            if request.path.endswith("service-worker.js"):
+                response.headers["Service-Worker-Allowed"] = "/"
+
             return response
 
         @self.superset_app.after_request

Reply via email to