Skip to content

fix(chart-customizations): support migration of dynamic group by#37176

Merged
sadpandajoe merged 3 commits into
apache:masterfrom
DamianPendrak:fix/chart-customization-migration
Feb 20, 2026
Merged

fix(chart-customizations): support migration of dynamic group by#37176
sadpandajoe merged 3 commits into
apache:masterfrom
DamianPendrak:fix/chart-customization-migration

Conversation

@DamianPendrak
Copy link
Copy Markdown
Member

SUMMARY

The #36062 introduced changes to support more chart customization types. It does not handle the migration of the old dynamic group by. This is fixed in this PR

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

TESTING INSTRUCTIONS

  1. Checkout any commit before feat(dashboard): chart customizations modal and plugins #36062. For example 481bfa0
  2. Create dynamic group by for any dashboard
  3. Checkout to this PR
  4. The created dynamic group by should be visible in the sidebar and working properly

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@codeant-ai-for-open-source
Copy link
Copy Markdown
Contributor

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review Bot commented Jan 15, 2026

Code Review Agent Run #e96f10

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts - 1
    • TypeScript 'any' usage · Line 259-259
      The controlValues property uses 'any' type, which violates the project's strict no-any policy for TypeScript. Consider replacing with 'unknown' for better type safety in this legacy interface.
      Code suggestion
       @@ -257,4 +257,4 @@
      -  controlValues?: {
      -    enableEmptyFilter?: boolean;
      -    [key: string]: any;
      -  };
      +  controlValues?: {
      +    enableEmptyFilter?: boolean;
      +    [key: string]: unknown;
      +  };
Review Details
  • Files reviewed - 9 · Commit Range: d128507..d128507
    • superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts
    • superset-frontend/src/dashboard/actions/hydrate.js
    • superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
    • superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts
    • superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts
    • superset-frontend/src/dashboard/components/nativeFilters/state.ts
    • superset-frontend/src/dashboard/util/migrateChartCustomization.test.ts
    • superset-frontend/src/dashboard/util/migrateChartCustomization.ts
    • superset-frontend/src/dataMask/reducer.ts
  • Files skipped - 0
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot Bot added the dashboard:native-filters Related to the native filters of the Dashboard label Jan 15, 2026
@DamianPendrak DamianPendrak changed the title fix(chart-customizations) support migration of dynamic group by fix(chart-customizations): support migration of dynamic group by Jan 15, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 15, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit d128507
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6969275b682be8000877e073
😎 Deploy Preview https://deploy-preview-37176--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@@ -96,8 +100,16 @@ const selectChartCustomizationConfiguration = createSelector(
state.dashboardInfo.metadata?.chart_customization_config || EMPTY_ARRAY,
selectDashboardChartIds,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The selector accesses state.dashboardInfo.metadata without checking whether state.dashboardInfo exists; if dashboardInfo is undefined this will throw at runtime. Add optional chaining on dashboardInfo so the selector safely falls back to EMPTY_ARRAY when dashboardInfo is not present. [null pointer]

Severity Level: Critical 🚨
- ❌ Dashboard render crashes on missing dashboardInfo.
- ❌ Chart customizations sidebar fails to mount.
- ⚠️ Unit tests mocking partial store may fail.
Suggested change
selectDashboardChartIds,
state.dashboardInfo?.metadata?.chart_customization_config || EMPTY_ARRAY,
Steps of Reproduction ✅
1. Open the dashboard UI component that uses chart customizations which calls
useChartCustomizationConfiguration (see useChartCustomizationConfiguration at
superset-frontend/src/dashboard/components/nativeFilters/state.ts:127).

2. During initial render the selector selectChartCustomizationConfiguration is executed
(defined at superset-frontend/src/dashboard/components/nativeFilters/state.ts:100-101).

3. If Redux state has no dashboardInfo key (state.dashboardInfo === undefined) the
expression at superset-frontend/src/dashboard/components/nativeFilters/state.ts:101
attempts to read `.metadata` on undefined and throws a TypeError.

4. Reproduce in tests by mocking react-redux useSelector to return a store object without
dashboardInfo and rendering any component that calls useChartCustomizationConfiguration;
the component render will throw at the selector line shown above.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/dashboard/components/nativeFilters/state.ts
**Line:** 101:101
**Comment:**
	*Null Pointer: The selector accesses `state.dashboardInfo.metadata` without checking whether `state.dashboardInfo` exists; if `dashboardInfo` is undefined this will throw at runtime. Add optional chaining on `dashboardInfo` so the selector safely falls back to `EMPTY_ARRAY` when `dashboardInfo` is not present.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.

Comment on lines +226 to +232
const hasLegacyFormat = rawChartCustomizationConfig.some(item =>
isLegacyChartCustomizationFormat(item),
);

const chartCustomizationConfig = hasLegacyFormat
? migrateChartCustomizationArray(rawChartCustomizationConfig)
: (rawChartCustomizationConfig as ChartCustomization[]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Logic bug / unsafe migration: when any legacy item exists the code calls migrateChartCustomizationArray with the entire rawChartCustomizationConfig (including already-modern items), potentially re-migrating or corrupting items that are already in the new format; instead, migrate only legacy items and preserve existing new items (while keeping original order). [possible bug]

Severity Level: Critical 🚨
- ❌ Dashboard hydration can corrupt chart customization entries.
- ❌ Sidebar chart customization shows incorrect items.
- ⚠️ Affects dashboards with mixed-format customization arrays.
- ⚠️ Migration may alter saved dashboard configuration.
Suggested change
const hasLegacyFormat = rawChartCustomizationConfig.some(item =>
isLegacyChartCustomizationFormat(item),
);
const chartCustomizationConfig = hasLegacyFormat
? migrateChartCustomizationArray(rawChartCustomizationConfig)
: (rawChartCustomizationConfig as ChartCustomization[]);
// Migrate only legacy items and preserve non-legacy items in original order.
const legacyItems = rawChartCustomizationConfig.filter(item =>
isLegacyChartCustomizationFormat(item),
);
const migratedLegacyItems = legacyItems.length
? migrateChartCustomizationArray(legacyItems)
: [];
// Reconstruct final array preserving order: replace legacy entries with migrated ones.
let migratedIndex = 0;
const chartCustomizationConfig = rawChartCustomizationConfig.map(item =>
isLegacyChartCustomizationFormat(item)
? (migratedLegacyItems[migratedIndex++] as ChartCustomization)
: (item as ChartCustomization),
);
Steps of Reproduction ✅
1. Open the dashboard page that triggers dashboard hydration. The HYDRATE_DASHBOARD action
is handled by the reducer at superset-frontend/src/dataMask/reducer.ts in the
HYDRATE_DASHBOARD case (lines ~220-320). The migration code runs at lines 223-232 in that
file.

2. Ensure the dashboard metadata returned from the backend includes
chart_customization_config with a mix of legacy-format and already-modern-format items
(the reducer reads metadata?.chart_customization_config at line 223).

3. When the HYDRATE_DASHBOARD action is dispatched, the reducer evaluates hasLegacyFormat
using isLegacyChartCustomizationFormat (imported from
src/dashboard/util/migrateChartCustomization) at lines 226-228.

4. Because at least one legacy item exists, the current code calls
migrateChartCustomizationArray with the entire rawChartCustomizationConfig array (line
231). If migrateChartCustomizationArray expects legacy-only inputs or transforms items
generically, this will re-process modern items and can change/corrupt them. Observe
unexpected/mutated chart customization entries after hydration in the dashboard UI
(sidebar customizations missing or altered), originating from reducer lines 223-232.

Note: This reproduces concretely by creating a dashboard metadata payload containing
mixed-format chart_customization_config and loading that dashboard so the
HYDRATE_DASHBOARD reducer branch executes (see reducer.ts lines 220-236).
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/dataMask/reducer.ts
**Line:** 226:232
**Comment:**
	*Possible Bug: Logic bug / unsafe migration: when any legacy item exists the code calls `migrateChartCustomizationArray` with the entire `rawChartCustomizationConfig` (including already-modern items), potentially re-migrating or corrupting items that are already in the new format; instead, migrate only legacy items and preserve existing new items (while keeping original order).

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

migrateChartCustomizationArray checks if the item is legacy and only then migrates it

@codeant-ai-for-open-source
Copy link
Copy Markdown
Contributor

CodeAnt AI finished reviewing your PR.

@sadpandajoe sadpandajoe added the 🎪 ⚡ showtime-trigger-start Create new ephemeral environment for this PR label Jan 15, 2026
@github-actions github-actions Bot added 🎪 b29ce96 🚦 building 🎪 ⌛ 48h Environment expires after 48 hours (default) and removed 🎪 ⚡ showtime-trigger-start Create new ephemeral environment for this PR labels Jan 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎪 Showtime is building environment on GHA for b29ce96

@github-actions
Copy link
Copy Markdown
Contributor

🎪 Showtime is building environment on GHA for e75d556

@github-actions
Copy link
Copy Markdown
Contributor

🎪 Showtime deployed environment on GHA for e75d556

Environment: http://35.93.128.118:8080 (admin/admin)
Lifetime: 72h auto-cleanup
Updates: New commits create fresh environments automatically

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 3, 2026

⚠️ DEPRECATED WORKFLOW ⚠️

@sadpandajoe This workflow is deprecated! Please use the new Superset Showtime system instead:

Processing your ephemeral environment request here. Action: up. More information on how to use or configure ephemeral environments

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 3, 2026

@sadpandajoe Ephemeral environment spinning up at http://54.214.116.16:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.

@rebecanogueira-preset
Copy link
Copy Markdown

@DamianPendrak has this been tested yet or do you need QA validation for this PR?

@DamianPendrak
Copy link
Copy Markdown
Member Author

@rebecanogueira-preset I need QA validation for this PR

@DamianPendrak DamianPendrak force-pushed the fix/chart-customization-migration branch from e75d556 to e492958 Compare February 15, 2026 08:49
@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review Bot commented Feb 15, 2026

Code Review Agent Run #5239b6

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts - 1
    • Code duplication in prefix checks · Line 91-92
      The code manually checks for CHART_CUSTOMIZATION_PREFIX and LEGACY_GROUPBY_PREFIX instead of using the existing isChartCustomization helper function. This creates duplication and risks inconsistency if the helper's logic changes. Consider refactoring to use the helper for better maintainability.
Review Details
  • Files reviewed - 9 · Commit Range: c4393b7..e492958
    • superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts
    • superset-frontend/src/dashboard/actions/hydrate.ts
    • superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
    • superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts
    • superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts
    • superset-frontend/src/dashboard/components/nativeFilters/state.ts
    • superset-frontend/src/dashboard/util/migrateChartCustomization.test.ts
    • superset-frontend/src/dashboard/util/migrateChartCustomization.ts
    • superset-frontend/src/dataMask/reducer.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sadpandajoe sadpandajoe removed the hold:testing! On hold for testing label Feb 20, 2026
@sadpandajoe sadpandajoe merged commit 1a77e17 into apache:master Feb 20, 2026
69 of 70 checks passed
@dosubot
Copy link
Copy Markdown

dosubot Bot commented Feb 20, 2026

Related Documentation

Checked 0 published document(s) in 2 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dashboard:native-filters Related to the native filters of the Dashboard packages size/XL testenv-up 🎪 ⌛ 48h Environment expires after 48 hours (default)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants