You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by so...@apache.org on 2026/06/05 18:37:02 UTC
(superset) branch master updated: fix(dashboard): prevent divider display controls from reverting on second save (#40696)
This is an automated email from the ASF dual-hosted git repository.
yousoph 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 e956f82224b fix(dashboard): prevent divider display controls from reverting on second save (#40696)
e956f82224b is described below
commit e956f82224b3352562542e8d5514a898c60251e2
Author: yousoph <so...@gmail.com>
AuthorDate: Fri Jun 5 11:36:55 2026 -0700
fix(dashboard): prevent divider display controls from reverting on second save (#40696)
Co-authored-by: Claude Sonnet 4.6 <no...@anthropic.com>
---
.../FiltersConfigModal/FiltersConfigModal.test.tsx | 133 +++++++++++++++++++++
.../FiltersConfigModal/FiltersConfigModal.tsx | 18 ++-
2 files changed, 148 insertions(+), 3 deletions(-)
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.test.tsx
index 3583671ad59..ebdd0038077 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.test.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.test.tsx
@@ -800,6 +800,139 @@ test('does not auto-create a filter when createNewOnOpen is false', () => {
expect(screen.queryByText(DATASET_REGEX)).not.toBeInTheDocument();
});
+test('enables save button and includes updated title when editing an existing divider', async () => {
+ jest.useFakeTimers();
+
+ const nativeFilterDividerConfig = [
+ {
+ id: 'NATIVE_FILTER_DIVIDER-1',
+ type: 'DIVIDER' as const,
+ title: 'First Edit',
+ description: '',
+ scope: { rootPath: ['ROOT'], excluded: [] },
+ },
+ ];
+
+ const state = {
+ ...defaultState(),
+ dashboardInfo: {
+ metadata: {
+ native_filter_configuration: nativeFilterDividerConfig,
+ },
+ },
+ dashboardLayout,
+ };
+
+ const onSave = jest.fn();
+
+ defaultRender(state, {
+ ...props,
+ createNewOnOpen: false,
+ initialFilterId: 'NATIVE_FILTER_DIVIDER-1',
+ onSave,
+ });
+
+ // Save button should be disabled when no changes have been made
+ expect(screen.getByRole('button', { name: SAVE_REGEX })).toBeDisabled();
+
+ // Editing the title field should mark the divider modified and enable save
+ const titleInput = screen.getByRole('textbox', { name: /^title$/i });
+ await userEvent.clear(titleInput);
+ await userEvent.type(titleInput, 'Second Edit');
+
+ jest.advanceTimersByTime(500);
+ jest.useRealTimers();
+
+ await waitFor(() =>
+ expect(
+ screen.getByRole('button', { name: SAVE_REGEX }),
+ ).not.toBeDisabled(),
+ );
+
+ await userEvent.click(screen.getByRole('button', { name: SAVE_REGEX }));
+
+ await waitFor(() =>
+ expect(onSave).toHaveBeenCalledWith(
+ expect.objectContaining({
+ filterChanges: expect.objectContaining({
+ modified: expect.arrayContaining([
+ expect.objectContaining({
+ id: 'NATIVE_FILTER_DIVIDER-1',
+ title: 'Second Edit',
+ }),
+ ]),
+ }),
+ }),
+ ),
+ );
+}, 30000);
+
+test('enables save button and includes updated title when editing an existing chart customization divider', async () => {
+ jest.useFakeTimers();
+
+ const chartCustomizationDividerConfig = [
+ {
+ id: 'CHART_CUSTOMIZATION_DIVIDER-1',
+ type: 'CHART_CUSTOMIZATION_DIVIDER' as const,
+ title: 'First Edit',
+ description: '',
+ },
+ ];
+
+ const state = {
+ ...defaultState(),
+ dashboardInfo: {
+ metadata: {
+ chart_customization_config: chartCustomizationDividerConfig,
+ },
+ },
+ dashboardLayout,
+ };
+
+ const onSave = jest.fn();
+
+ defaultRender(state, {
+ ...props,
+ createNewOnOpen: false,
+ initialFilterId: 'CHART_CUSTOMIZATION_DIVIDER-1',
+ onSave,
+ });
+
+ // Save button should be disabled when no changes have been made
+ expect(screen.getByRole('button', { name: SAVE_REGEX })).toBeDisabled();
+
+ // Editing the title field should mark the divider modified and enable save
+ const titleInput = screen.getByRole('textbox', { name: /^title$/i });
+ await userEvent.clear(titleInput);
+ await userEvent.type(titleInput, 'Second Edit');
+
+ jest.advanceTimersByTime(500);
+ jest.useRealTimers();
+
+ await waitFor(() =>
+ expect(
+ screen.getByRole('button', { name: SAVE_REGEX }),
+ ).not.toBeDisabled(),
+ );
+
+ await userEvent.click(screen.getByRole('button', { name: SAVE_REGEX }));
+
+ await waitFor(() =>
+ expect(onSave).toHaveBeenCalledWith(
+ expect.objectContaining({
+ customizationChanges: expect.objectContaining({
+ modified: expect.arrayContaining([
+ expect.objectContaining({
+ id: 'CHART_CUSTOMIZATION_DIVIDER-1',
+ title: 'Second Edit',
+ }),
+ ]),
+ }),
+ }),
+ ),
+ );
+}, 30000);
+
test('empty state disappears when a filter is added via dropdown', async () => {
defaultRender(defaultState(), {
...props,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
index 3cfe83434fe..44ba434ab66 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
@@ -57,6 +57,7 @@ import {
isFilterId,
isChartCustomizationId,
transformDividerId,
+ isDivider,
} from './utils';
import { ConfigModalContent } from './ConfigModalContent';
import ConfigModalSidebar from './ConfigModalSidebar';
@@ -470,9 +471,20 @@ function FiltersConfigModal({
[modalSaveLogic, setSaveAlertVisible],
);
- const handleValuesChange = useMemo(
- () => debouncedHandleErroredItems,
- [debouncedHandleErroredItems],
+ const handleValuesChange = useCallback(
+ (changedValues: Partial<NativeFiltersForm>) => {
+ debouncedHandleErroredItems();
+ // DividerConfigForm doesn't call handleModifyItem on change the way
+ // FiltersConfigForm does, so detect divider field changes here and mark
+ // the divider as modified so canSave becomes true and the save payload
+ // includes the updated divider values.
+ Object.keys(changedValues?.filters ?? {}).forEach(id => {
+ if (isDivider(id)) {
+ handleModifyItem(id);
+ }
+ });
+ },
+ [debouncedHandleErroredItems, handleModifyItem],
);
const handleActiveFilterPanelChange = useCallback(