You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2026/04/01 18:51:43 UTC
(superset) 08/15: fix(dashboard): live CSS preview in PropertiesModal (#38960)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch 6.1
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 5d8d170093deecb1a740ad3772d85681dfccbb6c
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Tue Mar 31 15:00:20 2026 -0300
fix(dashboard): live CSS preview in PropertiesModal (#38960)
Co-authored-by: Claude Sonnet 4.6 <no...@anthropic.com>
(cherry picked from commit d4d22909cb412c3b38d5f5077b3cf8bfe96df4ff)
---
.../dashboard/components/PropertiesModal/index.tsx | 56 +++++++++++++++++++++-
1 file changed, 54 insertions(+), 2 deletions(-)
diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
index b53bfd6fb66..d472923d143 100644
--- a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
@@ -53,6 +53,7 @@ import {
setColorScheme,
setDashboardMetadata,
} from 'src/dashboard/actions/dashboardState';
+import { dashboardInfoChanged } from 'src/dashboard/actions/dashboardInfo';
import { areObjectsEqual } from 'src/reduxUtils';
import { StandardModal, useModalValidation } from 'src/components/Modal';
import { validateRefreshFrequency } from '../RefreshFrequency';
@@ -143,6 +144,8 @@ const PropertiesModal = ({
>([]);
const categoricalSchemeRegistry = getCategoricalSchemeRegistry();
const originalDashboardMetadata = useRef<Record<string, any>>({});
+ const originalCss = useRef<string | null>(null);
+ const cssDebounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
const handleErrorResponse = async (response: Response) => {
const { error, statusText, message } = await getClientErrorObject(response);
@@ -195,6 +198,9 @@ const PropertiesModal = ({
setOwners(owners);
setRoles(roles);
setCustomCss(css || '');
+ if (originalCss.current === null) {
+ originalCss.current = css || '';
+ }
setCurrentColorScheme(metadata?.color_scheme);
setSelectedThemeId(theme?.id || null);
@@ -269,7 +275,19 @@ const PropertiesModal = ({
setRoles(parsedRoles);
};
- const handleOnCancel = () => onHide();
+ const handleOnCancel = () => {
+ if (cssDebounceTimer.current) {
+ clearTimeout(cssDebounceTimer.current);
+ cssDebounceTimer.current = null;
+ }
+ if (originalCss.current !== null) {
+ dispatch(dashboardInfoChanged({ css: originalCss.current }));
+ dispatch(
+ setColorScheme(originalDashboardMetadata.current.color_scheme ?? ''),
+ );
+ }
+ onHide();
+ };
const onColorSchemeChange = (
colorScheme = '',
@@ -429,6 +447,14 @@ const PropertiesModal = ({
}
};
+ // Must be defined before the data-loading effect so it runs first when show
+ // becomes true, ensuring handleDashboardData sees null and captures original CSS
+ useEffect(() => {
+ if (show) {
+ originalCss.current = null;
+ }
+ }, [show]);
+
useEffect(() => {
if (show) {
// Reset loading state when modal opens
@@ -596,6 +622,32 @@ const PropertiesModal = ({
const isDataReady = !isLoading && dashboardInfo;
+ // Debounced live CSS preview so changes are reflected on the dashboard
+ // without clicking Apply. Called only on user edits, not on data load.
+ const handleCustomCssChange = useCallback(
+ (css: string) => {
+ setCustomCss(css);
+ if (cssDebounceTimer.current) {
+ clearTimeout(cssDebounceTimer.current);
+ cssDebounceTimer.current = null;
+ }
+ cssDebounceTimer.current = setTimeout(() => {
+ dispatch(dashboardInfoChanged({ css }));
+ }, 500);
+ },
+ [dispatch],
+ );
+
+ useEffect(
+ () => () => {
+ if (cssDebounceTimer.current) {
+ clearTimeout(cssDebounceTimer.current);
+ cssDebounceTimer.current = null;
+ }
+ },
+ [],
+ );
+
// Validate basic section when title changes or data loads
useEffect(() => {
if (isDataReady) {
@@ -722,7 +774,7 @@ const PropertiesModal = ({
showChartTimestamps={showChartTimestamps}
onThemeChange={handleThemeChange}
onColorSchemeChange={onColorSchemeChange}
- onCustomCssChange={setCustomCss}
+ onCustomCssChange={handleCustomCssChange}
onShowChartTimestampsChange={setShowChartTimestamps}
addDangerToast={addDangerToast}
/>