korbit-ai[bot] commented on code in PR #34764:
URL: https://github.com/apache/superset/pull/34764#discussion_r2286188310


##########
superset/templates/superset/spa.html:
##########
@@ -70,16 +70,41 @@
 
     {% block body %}
       <div id="app" data-bootstrap="{{ bootstrap_data }}">
-        <img
-          src="{{ assets_prefix }}/static/assets/images/loading.gif"
-          style="
-            width: 50px;
-            position: absolute;
-            top: 50%;
-            left: 50%;
-            transform: translate(-50%, -50%);
-          "
-        />
+        {% set default_theme = theme_data.get('default', {}) %}
+        {% set theme_tokens = default_theme.get('token', {}) %}
+
+        {% if theme_tokens.get('brandSpinnerSvg') %}
+          <!-- SVG Priority: Inline SVG content -->
+          <div style="width: 50px; position: absolute; top: 50%; left: 50%; 
transform: translate(-50%, -50%);">

Review Comment:
   ### Redundant Inline Styles <sub>![category 
Performance](https://img.shields.io/badge/Performance-4f46e5)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Duplicate inline styles repeated three times in the template causing 
unnecessary code bloat.
   
   
   ###### Why this matters
   Redundant CSS definitions increase the HTML size and parsing time 
unnecessarily.
   
   ###### Suggested change ∙ *Feature Preview*
   Extract the common styles into a CSS class in the stylesheet:
   ```html
   <style>
   .centered-spinner {
     width: 50px;
     position: absolute;
     top: 50%;
     left: 50%;
     transform: translate(-50%, -50%);
   }
   </style>
   ```
   Then use `class="centered-spinner"` in the markup.
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/15bd0529-77b3-41b2-a0db-948b4bec5975/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/15bd0529-77b3-41b2-a0db-948b4bec5975?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/15bd0529-77b3-41b2-a0db-948b4bec5975?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/15bd0529-77b3-41b2-a0db-948b4bec5975?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/15bd0529-77b3-41b2-a0db-948b4bec5975)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:abd1ceb4-0398-43b7-b68a-0f6caf8849c8 -->
   
   
   [](abd1ceb4-0398-43b7-b68a-0f6caf8849c8)



##########
superset/templates/superset/spa.html:
##########
@@ -70,16 +70,41 @@
 
     {% block body %}
       <div id="app" data-bootstrap="{{ bootstrap_data }}">
-        <img
-          src="{{ assets_prefix }}/static/assets/images/loading.gif"
-          style="
-            width: 50px;
-            position: absolute;
-            top: 50%;
-            left: 50%;
-            transform: translate(-50%, -50%);
-          "
-        />
+        {% set default_theme = theme_data.get('default', {}) %}
+        {% set theme_tokens = default_theme.get('token', {}) %}
+
+        {% if theme_tokens.get('brandSpinnerSvg') %}
+          <!-- SVG Priority: Inline SVG content -->
+          <div style="width: 50px; position: absolute; top: 50%; left: 50%; 
transform: translate(-50%, -50%);">
+            {{ theme_tokens.brandSpinnerSvg | safe }}

Review Comment:
   ### Unsafe SVG Rendering <sub>![category 
Security](https://img.shields.io/badge/Security-e11d48)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Unescaped SVG content is being rendered directly into the HTML using the 
'safe' filter, which could lead to XSS vulnerabilities if the 
theme_tokens.brandSpinnerSvg content is not properly validated.
   
   
   ###### Why this matters
   If the SVG content contains malicious JavaScript code and isn't properly 
sanitized before being stored in theme_tokens, it could execute in users' 
browsers when the page loads.
   
   ###### Suggested change ∙ *Feature Preview*
   Implement SVG content validation and sanitization before storing it in 
theme_tokens. Consider using a dedicated SVG sanitizer library or strict 
validation rules to ensure only safe SVG content is allowed.
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5ab4137e-627b-4140-81fb-4df744a41d76/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5ab4137e-627b-4140-81fb-4df744a41d76?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5ab4137e-627b-4140-81fb-4df744a41d76?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5ab4137e-627b-4140-81fb-4df744a41d76?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5ab4137e-627b-4140-81fb-4df744a41d76)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:4600fe37-8423-4b03-a6b8-f01552054e9f -->
   
   
   [](4600fe37-8423-4b03-a6b8-f01552054e9f)



##########
superset-frontend/packages/superset-ui-core/src/components/Loading/index.tsx:
##########
@@ -51,11 +51,23 @@
   image,
   className,
 }: LoadingProps) {
+  const theme = useTheme();
+
+  // Precedence: explicit image prop > brandSpinnerSvg > brandSpinnerUrl > 
default
+  const getSpinnerSource = () => {
+    if (image) return image; // Explicit prop takes highest precedence
+    if (theme.brandSpinnerSvg) {
+      return `data:image/svg+xml;base64,${btoa(theme.brandSpinnerSvg)}`;
+    }
+    if (theme.brandSpinnerUrl) return theme.brandSpinnerUrl;
+    return Loader; // Default loading.gif
+  };

Review Comment:
   ### Move Pure Function Outside Component <sub>![category 
Design](https://img.shields.io/badge/Design-0d9488)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   The getSpinnerSource function is defined inside the component, causing it to 
be recreated on every render. This function doesn't depend on any props or 
state that change frequently.
   
   
   ###### Why this matters
   Recreating this function on every render is unnecessary and impacts 
performance optimization techniques like memoization. It also makes the 
function less reusable across components.
   
   ###### Suggested change ∙ *Feature Preview*
   ```typescript
   const getSpinnerSource = (image: string | undefined, theme: Theme) => {
       if (image) return image;
       if (theme.brandSpinnerSvg) {
         return `data:image/svg+xml;base64,${btoa(theme.brandSpinnerSvg)}`;
       }
       if (theme.brandSpinnerUrl) return theme.brandSpinnerUrl;
       return Loader;
   };
   
   export function Loading({ position = 'floating', image, className }: 
LoadingProps) {
     const theme = useTheme();
     return (
       <LoaderImg
         ...
         src={getSpinnerSource(image, theme)}
         ...
       />
     );
   }
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/f2fdd124-151e-4ed8-b049-8a9c6364b49f/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/f2fdd124-151e-4ed8-b049-8a9c6364b49f?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/f2fdd124-151e-4ed8-b049-8a9c6364b49f?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/f2fdd124-151e-4ed8-b049-8a9c6364b49f?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/f2fdd124-151e-4ed8-b049-8a9c6364b49f)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:612b1e1d-6eea-4f89-a99c-0ac277c9df51 -->
   
   
   [](612b1e1d-6eea-4f89-a99c-0ac277c9df51)



##########
superset/initialization/__init__.py:
##########
@@ -630,15 +630,24 @@ def apply_http_headers(response: Response) -> Response:
         def get_common_bootstrap_data() -> dict[str, Any]:
             # Import here to avoid circular imports
             from superset.utils import json
-            from superset.views.base import common_bootstrap_payload
+            from superset.views.base import (
+                common_bootstrap_payload,
+                get_theme_bootstrap_data,
+            )
 
             def serialize_bootstrap_data() -> str:
                 return json.dumps(
                     {"common": common_bootstrap_payload()},
                     default=json.pessimistic_json_iso_dttm_ser,
                 )
 
-            return {"bootstrap_data": serialize_bootstrap_data}
+            # Get theme data for direct template access
+            theme_data = get_theme_bootstrap_data()
+
+            return {
+                "bootstrap_data": serialize_bootstrap_data,
+                "theme_data": theme_data.get("theme", {}),
+            }

Review Comment:
   ### Missing Theme Data Null Check <sub>![category 
Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   The theme_data dictionary is accessed without checking if 
get_theme_bootstrap_data() returned None, which could lead to a NoneType error 
if the theme data retrieval fails.
   
   
   ###### Why this matters
   If theme data retrieval fails, the application could crash when trying to 
call .get() on None, preventing the page from loading.
   
   ###### Suggested change ∙ *Feature Preview*
   Add a null check before accessing the theme data:
   ```python
   theme_data = get_theme_bootstrap_data() or {}
   
   return {
       "bootstrap_data": serialize_bootstrap_data,
       "theme_data": theme_data.get("theme", {}),
   }
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b2dc0e7b-7357-41e9-95e0-f00d865b98f7/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b2dc0e7b-7357-41e9-95e0-f00d865b98f7?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b2dc0e7b-7357-41e9-95e0-f00d865b98f7?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b2dc0e7b-7357-41e9-95e0-f00d865b98f7?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b2dc0e7b-7357-41e9-95e0-f00d865b98f7)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:6cb589fc-0670-489c-b35d-f2f83426c0fd -->
   
   
   [](6cb589fc-0670-489c-b35d-f2f83426c0fd)



##########
superset-frontend/packages/superset-ui-core/src/components/Loading/index.tsx:
##########
@@ -51,11 +51,23 @@ export function Loading({
   image,
   className,
 }: LoadingProps) {
+  const theme = useTheme();
+
+  // Precedence: explicit image prop > brandSpinnerSvg > brandSpinnerUrl > 
default
+  const getSpinnerSource = () => {
+    if (image) return image; // Explicit prop takes highest precedence
+    if (theme.brandSpinnerSvg) {
+      return `data:image/svg+xml;base64,${btoa(theme.brandSpinnerSvg)}`;

Review Comment:
   ### Unsafe SVG Base64 Encoding <sub>![category 
Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Using btoa() for SVG base64 encoding can fail with Unicode characters in the 
SVG content, as btoa() only works with ASCII characters.
   
   
   ###### Why this matters
   If the SVG contains any non-ASCII characters (like in attributes or 
content), the code will throw a 'Character Out Of Range' error, causing the 
loading spinner to fail.
   
   ###### Suggested change ∙ *Feature Preview*
   Use a safe base64 encoding function that handles Unicode characters 
correctly:
   ```typescript
   const toBase64 = (str: string) => {
     try {
       return btoa(unescape(encodeURIComponent(str)));
     } catch (e) {
       console.error('Failed to encode SVG:', e);
       return '';
     }
   }
   
   // Usage in getSpinnerSource
   if (theme.brandSpinnerSvg) {
     return `data:image/svg+xml;base64,${toBase64(theme.brandSpinnerSvg)}`;
   }
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/538697fb-eb9c-4213-ab6a-39e8423d99f7/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/538697fb-eb9c-4213-ab6a-39e8423d99f7?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/538697fb-eb9c-4213-ab6a-39e8423d99f7?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/538697fb-eb9c-4213-ab6a-39e8423d99f7?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/538697fb-eb9c-4213-ab6a-39e8423d99f7)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:50c4ad19-b0ea-4580-8e76-c3112409c7ae -->
   
   
   [](50c4ad19-b0ea-4580-8e76-c3112409c7ae)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to