superset icon indicating copy to clipboard operation
superset copied to clipboard

feat(table): add chart visualization to AG Grid table column

Open andre-fong opened this issue 3 weeks ago • 8 comments

User description

SUMMARY

Use charts as custom component renderers in AG Grid (Table V2) to render charts in tables and create a POC to demonstrate custom cell renderers using the Community version. We will use AG Grid’s custom cell rendering functionality to support rendering different charts (e.g., sparkline, histogram, etc.) ourselves by building custom cell renderers for sparkline and minibar charts. These charts will visualise the values of the selected metrics columns within their row.

User Requirements

Usage (inside Table V2):

  1. Add a Chart Column (can add multiple) in the control panel for Table V2

  2. Configure the Chart Column:

    • Click on "Add a new chart column"
    • Select chart type and input desired settings
    • The renderer will visualize all numeric values from that row

NOTE: Charts are configured at the column level (TableColumnConfig); a column may only display one type of chart, all of which will have the same configuration (e.g. same color). This means there can only be one kind of chartType for each column (i.e., a column can and should only render either only sparkline charts or minibar charts, never more than one).

  1. Requirements:
    • User Responsibility: Ensure row contains relevant columns (Renderers filter strings and null before drawing charts)
    • Ensure column order reflects desired visualisation sequence (e.g., Q1, Q2, Q3, Q4)

Example Use Cases:

Expected Usage:

Product | Q1 | Q2 | Q3 | Q4 | Trend (new chart column) Widget A | 100 | 150 | 120 | 180 | [sparkline: 100→150→120→180]

(Example) User Responsibility when selecting columns:

Product | Genre | Q1 | Q2 | Q3 | Q4 | Canada Total | Trend Widget A | Electronics | 100 | 150 | 120 | 180 | 550 | [sparkline: 100→150→120→180→550]

  • "Genre" is automatically skipped (string)
  • "Canada Total" is included in sparkline (numeric) - depending on user goals this may not be desired
  • User should exclude or reorder columns to avoid this

Known Limitations

  • No column-specific filtering (all columns with numeric values are considered for visualisation)
  • User cannot specify which columns to include/exclude per chart
  • Column order determines visualisation order

Future Enhancements

  • Add ability for users to select which columns to consider for visualisation
  • Separate chart configuration from table column configuration (maybe to potentially fetch data outside of the table?)
  • More supported charts!

Notes:

  1. All existing TableColumnConfig properties remain unchanged
  2. New chartType and chart configuration fields (color, strokeWidth) are optional
  3. Only columns with column type of GenericDataType.Chart will go through chart processing/transformation logic, other columns maintain their old data flow (backwards compatibility)

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

image image image image

And we have just created a sparkline chart column! Here's what the mini-bar chart looks like as well:

image

TESTING INSTRUCTIONS

  1. Set AG_GRID_TABLE_ENABLED to True in superset/config.py
  2. Add a new 'Table V2' chart
  3. Add dimensions and metrics to test
  4. Under the new 'Chart columns' section, click on 'Add a new chart column' and enter a column label
  5. View your newly added column in the table section with a rendered chart
  6. (optional) Customize chart settings in the 'Customize' tab by clicking the chart column and clicking the 'Chart Settings' tab in the popover. Changes are rendered immediately

ADDITIONAL INFORMATION

  • [ ] Has associated issue:
  • [x] Required feature flags: AG_GRID_TABLE_ENABLED
    • We enable AG_GRID_TABLE_ENABLED to turn on rendering for using the AG Grid table for Table V2, so that it can render the graphs in each cell
  • [x] Changes UI
    • Adds new cell renderers for Sparkline and Mini-bar charts in the table
    • Adds new 'Chart columns' control (draglist) in the 'Data' tab of the Table V2 control panel (and popover for setting column label)
    • Adds new column type under 'Customize columns' in the 'Customize' tab for a chart column (renders new chart anticon)
    • Adds new 'Chart Settings' tab in the 'Customize columns' popover
  • [ ] 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
  • [x] Introduces new feature or API
    • Introduced new feature, no API changes. Read more in the summary.
  • [ ] Removes existing feature or API

CodeAnt-AI Description

Let Table V2 show configurable sparkline and mini bar chart columns

What Changed

  • Added a “Chart columns” control in the Table V2 builder so users can append chart-only columns that visualize each row’s selected metrics
  • Enabled per-column chart settings (type: sparkline or mini bar, width, height, color, stroke width, show values, show points) via the existing column configuration panel
  • Introduced a chart data type with a dedicated chart icon so chart columns are clearly identified in column type labels
  • Made Table V2 (AG Grid table) enabled by default in the application configuration
  • Extended inline sparkline/mini bar rendering to work with both array and object row data and added tests to verify bar chart rendering and sparkline point/line styling

Impact

✅ Visual row-level trends directly inside Table V2 ✅ Customizable sparkline and mini bar columns in tables ✅ Table V2 experience enabled for all users by default

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

andre-fong avatar Nov 30 '25 19:11 andre-fong

🎪 Showtime is building environment on GHA for 030bebf

github-actions[bot] avatar Dec 01 '25 13:12 github-actions[bot]

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 68.00%. Comparing base (a745fd4) to head (2ceee15). :warning: Report is 34 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master   #36344       +/-   ##
===========================================
+ Coverage        0   68.00%   +68.00%     
===========================================
  Files           0      637      +637     
  Lines           0    46864    +46864     
  Branches        0     5088     +5088     
===========================================
+ Hits            0    31868    +31868     
- Misses          0    13716    +13716     
- Partials        0     1280     +1280     
Flag Coverage Δ
hive 43.73% <ø> (?)
mysql 67.06% <ø> (?)
postgres 67.11% <ø> (?)
presto 47.36% <ø> (?)
python 67.96% <ø> (?)
sqlite 66.73% <ø> (?)
unit 100.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Dec 01 '25 13:12 codecov[bot]

Hey there! It looks like you need to run pre-commit to unblock at least some (if not all) of the CI issues that are happening here. I'll try again to get showtime to spin up a test environment.

rusackas avatar Dec 01 '25 23:12 rusackas

CodeAnt AI is reviewing your PR.

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • [ ] Possible Bug
    The internal chartColumns state is initialized from the incoming value prop but is never updated when value changes after mount. If the control framework or parent component updates value externally (e.g., resetting controls, loading a saved chart, or applying undo/redo), this component will keep showing the stale local copy and emit outdated data via onChange. This controlled vs. uncontrolled mismatch should be validated.

  • [ ] Possible Bug
    Null metric values are currently coerced to 0 in both the chart data and the tooltip, which can misrepresent missing data as actual zeros. This may violate the intended behavior of "filtering nulls before drawing charts" and could confuse users interpreting the visualization.

  • [ ] Scale Domain Edge Case
    When all values in the input data (or effectively after bounds are applied) are identical, the computed scale domain will have equal min and max, which can cause rendering issues or warnings in scale/plot libraries that expect a non-zero domain range. It would be good to confirm how the downstream charting components behave in this situation and potentially guard against a zero-length domain.

  • [ ] Possible Bug
    parseArrayValue always returns a numeric array (including [] for unsupported inputs), so the if (!Array.isArray(value)) guard is never triggered. This likely defeats the intent of returning "N/A" for non-numeric or invalid row data and can lead to silently rendering empty sparklines instead of a clearer fallback.

  • [ ] Possible Bug
    The test that toggles showValues creates only a shallow copy of createMockParams and then mutates the nested col.config object. This means the shared createMockParams.col.config is permanently modified for subsequent tests, which can lead to inter-test coupling and flaky behavior depending on test execution order. The setup should avoid mutating shared nested objects.

  • [ ] Code Smell
    The Array.isArray guard right after parseArrayValue is inconsistent with parseArrayValue's implementation, which always returns an array. This makes the N/A branch effectively unreachable and suggests either a misunderstanding of parseArrayValue's contract or a missing check for an empty numeric array instead.

  • [ ] Possible Bug
    chartColor calls rgbToHex(color) when color is an object, but the underlying rgbToHex utility expects three numeric arguments (red, green, blue). If color is an RGB object or other non-string structure, this mismatch can cause runtime errors or incorrect colors. The reviewer should confirm the shape of color and adjust the call accordingly.

CodeAnt AI finished reviewing your PR.

This is so cool! What a great POC!

I was able to make a couple chart columns with one of the example datasets, which is awesome to see: image

So now I get how you've wired it up... if you add a bunch of metric columns to the chart, this scoops the metrics from each column into a chart for the row. Very cool! In this example, I can now see how each Language (row) stacks up for each metric, but also get these charts to see how the metrics stack up to each other for the row! How cool!

I think @kasiazjc and @yousoph would love to see this... it opens up a slew of possibilities.

  1. This feature is already useful as-is, though I might have some feedback about re-jiggering some of the controls (which are only relevant in certain cases, so we can probably hide several of them most of the time. Happy to give this granular feedback if you want to optimize the UI a bit here :D

  2. I could imagine an alternate version of controls to power the charts. The interpretation I think might get a lot of use is to have each chart column use TWO inputs... a dimension and a metric (i.e. x axis and y axis). That would allow some interesting use cases... let's say we're using "Vehicle Sales" here. You could have a row for each Vehicle Type, and the normal metric columns for Units Sold and Total Sales ($). But then if you add a chart column, you could pick... Units Sold as the Metric, and then pick the Timestamp column or the State column for an X axis. Or, similarly have a row per state, and display a chart showing a metric across Vehicle Types as your chart column. This would allow us to deprecate/remove the "Time-Series Table" chart.

  3. As a POC, this implementation is useful to show the way other places, too! It'd be a very separate project, but we seemingly could finally use these lil' chart types to show summary stats (i.e. histograms) at the tops of numeric columns in SQL Labs results table. Again, whole different scope of work, but it seems to share some of the same AG Grid building blocks.

Again, very nice concept... thanks for this POC! I'll provide some UI feedback on this implementation soon, and maybe we can get this version across the finish line!

rusackas avatar Dec 06 '25 05:12 rusackas

If you want to keep chipping at this, we can talk about some next moves. If you want to call it done, maybe we can target a feature branch instead of master — I can make one, and you can re-target the PR, then I (or others, including y'all) could keep chipping away at it :D

rusackas avatar Dec 08 '25 17:12 rusackas

Thanks for the awesome detailed review and taking the time to test this out! We're glad to hear you find value in the POC and that it's working well on your end 😄

I could imagine an alternate version of controls to power the charts. The interpretation I think might get a lot of use is to have each chart column use TWO inputs... a dimension and a metric (i.e. x axis and y axis).

Indeed, we thought about this interpretation as well! On top of our simpler method of plotting only the row's data in each chart, we could have each chart column have a dimension and a metric so that it displays its own data that does not necessarily have to be pre-populated in the table. We determined this interpretation to be out of scope for our POC due to its complexity, but we agree that this would leverage the strength of having a chart visualization inside of a table more! Something like the Finance demo table example from AG Grid's demo tables would be ideal.

If you want to keep chipping at this, we can talk about some next moves. If you want to call it done, maybe we can target a feature branch instead of master — I can make one, and you can re-target the PR, then I (or others, including y'all) could keep chipping away at it :D

I think this would be the best approach going forward. As our contribution to this project is wrapping up, this allows us to get the POC merged while leaving the door open for others to implement those future enhancements. I'm happy to re-target the PR once the feature branch is created, just let me know. Thanks Evan!

andre-fong avatar Dec 11 '25 04:12 andre-fong