-
Notifications
You must be signed in to change notification settings - Fork 17.4k
feat(table v2): add tooltip to table header #39287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SBIN2010
wants to merge
70
commits into
apache:master
Choose a base branch
from
SBIN2010:feature/add_AgGredTable_tooltip_to_table_header
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
19151d1
fix: fixed Add Metrics to Tree Chart (#29158)
SBIN2010 35aaeb6
fix: clear modal after CSS templates is added
SBIN2010 db3afda
Revert "fix: clear modal after CSS templates is added"
SBIN2010 9eea2e6
fix: tree metrics exclude validator
SBIN2010 3930c95
Merge branch 'apache:master' into master
SBIN2010 b355212
Merge branch 'apache:master' into master
SBIN2010 7200d6c
Merge branch 'apache:master' into master
SBIN2010 3049a3d
Merge branch 'apache:master' into master
SBIN2010 247aef8
Merge branch 'apache:master' into master
SBIN2010 b4678ec
Merge branch 'apache:master' into master
SBIN2010 0ae844d
Merge branch 'apache:master' into master
SBIN2010 49fc529
Merge branch 'apache:master' into master
SBIN2010 601dde2
fix: revert #30679
SBIN2010 66823a5
Merge branch 'apache:master' into master
SBIN2010 4f59629
Merge branch 'apache:master' into master
SBIN2010 a7ce4e9
Merge branch 'apache:master' into master
SBIN2010 1bf4fdd
fix
SBIN2010 1241867
Merge branch 'apache:master' into master
SBIN2010 045cf6b
Merge branch 'apache:master' into master
SBIN2010 acdba8a
Merge branch 'apache:master' into master
SBIN2010 4fb89c2
Merge branch 'apache:master' into master
SBIN2010 f47d28b
Merge branch 'apache:master' into master
SBIN2010 3bdf337
Merge branch 'apache:master' into master
SBIN2010 780a5d6
Merge branch 'apache:master' into master
SBIN2010 3c339df
Merge branch 'apache:master' into master
SBIN2010 798b7a6
Merge branch 'apache:master' into master
SBIN2010 2db564e
Merge branch 'apache:master' into master
SBIN2010 a58cfad
Merge branch 'apache:master' into master
SBIN2010 9ea0d2f
Merge branch 'apache:master' into master
SBIN2010 c6bbf53
Merge branch 'apache:master' into master
SBIN2010 5214e7a
Merge branch 'apache:master' into master
SBIN2010 d98105c
Merge branch 'apache:master' into master
SBIN2010 30b1576
Merge branch 'apache:master' into master
SBIN2010 4aaa27c
Merge branch 'apache:master' into master
SBIN2010 25c1987
Merge branch 'apache:master' into master
SBIN2010 c3854cb
Merge branch 'apache:master' into master
SBIN2010 e1c4909
Merge branch 'apache:master' into master
SBIN2010 c60bda8
Merge branch 'apache:master' into master
SBIN2010 964307e
Merge branch 'apache:master' into master
SBIN2010 df97cb7
Merge branch 'apache:master' into master
SBIN2010 6ef82fa
Merge branch 'apache:master' into master
SBIN2010 d0ae96c
Merge branch 'apache:master' into master
SBIN2010 725039c
Merge branch 'apache:master' into master
SBIN2010 727c59f
Merge branch 'apache:master' into master
SBIN2010 eeb04da
Merge branch 'apache:master' into master
SBIN2010 ca12644
Merge branch 'apache:master' into master
SBIN2010 45c1a1a
Merge branch 'apache:master' into master
SBIN2010 44708bf
Merge branch 'apache:master' into master
SBIN2010 59f2832
Merge branch 'apache:master' into master
SBIN2010 4cf50b1
Merge branch 'apache:master' into master
SBIN2010 e34d80e
Merge branch 'apache:master' into master
SBIN2010 a48fb9c
Merge branch 'apache:master' into master
SBIN2010 5100172
Merge branch 'apache:master' into master
SBIN2010 0bd47e9
Merge branch 'apache:master' into master
SBIN2010 17614b2
Merge branch 'apache:master' into master
SBIN2010 7143f13
Merge branch 'apache:master' into master
SBIN2010 d5776e6
Merge branch 'apache:master' into master
SBIN2010 8a5617e
Merge branch 'apache:master' into master
SBIN2010 a8dd1df
Merge branch 'apache:master' into master
SBIN2010 85a18a4
Merge branch 'apache:master' into master
SBIN2010 e15912c
Merge branch 'apache:master' into master
SBIN2010 e465243
Merge branch 'apache:master' into master
SBIN2010 20110eb
Merge branch 'apache:master' into master
SBIN2010 effbe6d
Merge branch 'apache:master' into master
SBIN2010 f9ed68e
Merge branch 'apache:master' into master
SBIN2010 838215a
feat: add add tooltip to table header
SBIN2010 67c3ac4
fix: conmments ai
SBIN2010 ce41a74
fix: add test to transformProps.test
SBIN2010 2d73c46
fix: test type
SBIN2010 f3a8d39
Merge branch 'master' into feature/add_AgGredTable_tooltip_to_table_h…
SBIN2010 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
266 changes: 266 additions & 0 deletions
266
superset-frontend/plugins/plugin-chart-ag-grid-table/test/transformProps.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,266 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| import transformProps from '../src/transformProps'; | ||
| import { TableChartProps } from '../src/types'; | ||
| import { GenericDataType } from '@apache-superset/core/common'; | ||
| import { QueryMode } from '@superset-ui/core'; | ||
|
|
||
| function createMockChartProps( | ||
| overrides: Partial<TableChartProps> = {}, | ||
| ): TableChartProps { | ||
| const defaultProps = { | ||
| height: 400, | ||
| width: 800, | ||
| rawFormData: { | ||
| viz_type: 'table', | ||
| datasource: '1__table', | ||
| query_mode: QueryMode.Aggregate, | ||
| metrics: [], | ||
| percent_metrics: [], | ||
| column_config: {}, | ||
| table_timestamp_format: '', | ||
| granularity_sqla: 'day', | ||
| time_range: 'No filter', | ||
| }, | ||
| queriesData: [ | ||
| { | ||
| data: [], | ||
| colnames: [], | ||
| coltypes: [], | ||
| rowcount: 0, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ], | ||
| datasource: { | ||
| columns: [], | ||
| metrics: [], | ||
| columnFormats: {}, | ||
| currencyFormats: {}, | ||
| verboseMap: {}, | ||
| }, | ||
| rawDatasource: { | ||
| columns: [], | ||
| metrics: [], | ||
| }, | ||
| filterState: {}, | ||
| hooks: { setDataMask: jest.fn(), onChartStateChange: jest.fn() }, | ||
| ownState: {}, | ||
| emitCrossFilters: false, | ||
| theme: {}, | ||
| ...overrides, | ||
| }; | ||
| return defaultProps as unknown as TableChartProps; | ||
| } | ||
|
|
||
| test('extracts description from datasource.columns for a regular column', () => { | ||
| const props = createMockChartProps({ | ||
| queriesData: [ | ||
| { | ||
| data: [{ col1: 'value' }], | ||
| colnames: ['col1'], | ||
| coltypes: [GenericDataType.String], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| } as unknown as TableChartProps['queriesData'][number], | ||
| ], | ||
| rawDatasource: { | ||
| columns: [ | ||
| { column_name: 'col1', description: 'This is a column description' }, | ||
| ], | ||
| metrics: [], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === 'col1'); | ||
| expect(columnMeta).toBeDefined(); | ||
| expect(columnMeta!.description).toBe('This is a column description'); | ||
| }); | ||
|
|
||
| test('extracts description from datasource.metrics for a metric column', () => { | ||
| const props = createMockChartProps({ | ||
| rawFormData: { | ||
| viz_type: 'table', | ||
| datasource: '1__table', | ||
| query_mode: QueryMode.Aggregate, | ||
| metrics: ['sum_sales'], | ||
| percent_metrics: [], | ||
| column_config: {}, | ||
| table_timestamp_format: '', | ||
| granularity_sqla: 'day', | ||
| time_range: 'No filter', | ||
| }, | ||
| queriesData: [ | ||
| { | ||
| data: [{ sum_sales: 100 }], | ||
| colnames: ['sum_sales'], | ||
| coltypes: [GenericDataType.Numeric], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ] as unknown as TableChartProps['queriesData'], | ||
| rawDatasource: { | ||
| columns: [], | ||
| metrics: [ | ||
| { metric_name: 'sum_sales', description: 'Total sales amount' }, | ||
| ], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === 'sum_sales'); | ||
| expect(columnMeta).toBeDefined(); | ||
| expect(columnMeta!.description).toBe('Total sales amount'); | ||
| }); | ||
|
|
||
| test('prefers column description over metric description when both exist with same key', () => { | ||
| const props = createMockChartProps({ | ||
| rawFormData: { | ||
| viz_type: 'table', | ||
| datasource: '1__table', | ||
| query_mode: QueryMode.Aggregate, | ||
| metrics: ['revenue'], | ||
| percent_metrics: [], | ||
| column_config: {}, | ||
| table_timestamp_format: '', | ||
| granularity_sqla: 'day', | ||
| time_range: 'No filter', | ||
| }, | ||
| queriesData: [ | ||
| { | ||
| data: [{ revenue: 500 }], | ||
| colnames: ['revenue'], | ||
| coltypes: [GenericDataType.Numeric], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ] as unknown as TableChartProps['queriesData'], | ||
| rawDatasource: { | ||
| columns: [{ column_name: 'revenue', description: 'Column desc' }], | ||
| metrics: [{ metric_name: 'revenue', description: 'Metric desc' }], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === 'revenue'); | ||
| expect(columnMeta!.description).toBe('Column desc'); | ||
| }); | ||
|
|
||
| test('handles percent metrics correctly – uses base metric name for lookup', () => { | ||
| const props = createMockChartProps({ | ||
| rawFormData: { | ||
| viz_type: 'table', | ||
| datasource: '1__table', | ||
| query_mode: QueryMode.Aggregate, | ||
| metrics: ['profit'], | ||
| percent_metrics: ['profit'], | ||
| column_config: {}, | ||
| table_timestamp_format: '', | ||
| granularity_sqla: 'day', | ||
| time_range: 'No filter', | ||
| }, | ||
| queriesData: [ | ||
| { | ||
| data: [{ '%profit': 0.15 }], | ||
| colnames: ['%profit'], | ||
| coltypes: [GenericDataType.Numeric], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ] as unknown as TableChartProps['queriesData'], | ||
| rawDatasource: { | ||
| columns: [], | ||
| metrics: [ | ||
| { metric_name: 'profit', description: 'Profit margin percent' }, | ||
| ], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === '%profit'); | ||
| expect(columnMeta).toBeDefined(); | ||
| expect(columnMeta!.description).toBe('Profit margin percent'); | ||
| }); | ||
|
|
||
| test('sets description to undefined when no matching column or metric is found', () => { | ||
| const props = createMockChartProps({ | ||
| queriesData: [ | ||
| { | ||
| data: [{ unknown_col: 'x' }], | ||
| colnames: ['unknown_col'], | ||
| coltypes: [GenericDataType.String], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ] as unknown as TableChartProps['queriesData'], | ||
| rawDatasource: { | ||
| columns: [], | ||
| metrics: [], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === 'unknown_col'); | ||
| expect(columnMeta!.description).toBeUndefined(); | ||
| }); | ||
|
|
||
| test('uses description from column even when verboseMap renames the column', () => { | ||
| const props = createMockChartProps({ | ||
| queriesData: [ | ||
| { | ||
| data: [{ col_x: 10 }], | ||
| colnames: ['col_x'], | ||
| coltypes: [GenericDataType.Numeric], | ||
| rowcount: 1, | ||
| applied_filters: [], | ||
| rejected_filters: [], | ||
| }, | ||
| ] as unknown as TableChartProps['queriesData'], | ||
| datasource: { | ||
| columns: [], | ||
| metrics: [], | ||
| columnFormats: {}, | ||
| currencyFormats: {}, | ||
| verboseMap: { col_x: 'Custom Label' }, | ||
| } as unknown as TableChartProps['datasource'], | ||
| rawDatasource: { | ||
| columns: [ | ||
| { column_name: 'col_x', description: 'Original column description' }, | ||
| ], | ||
| metrics: [], | ||
| }, | ||
| }); | ||
|
|
||
| const result = transformProps(props); | ||
| const { columns } = result; | ||
| const columnMeta = columns.find(c => c.key === 'col_x'); | ||
| expect(columnMeta!.label).toBe('Custom Label'); | ||
| expect(columnMeta!.description).toBe('Original column description'); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion:
processColumnsis memoized with a custom equality function, but this new logic now depends onrawDatasourceand the comparator does not account forrawDatasource.columns/rawDatasource.metrics. When datasource metadata changes (for example, updated column/metric descriptions) while other compared fields stay the same, memoization will incorrectly reuse stale column metadata and tooltip descriptions will not refresh. IncluderawDatasourcefields in theisEqualColumnscomparison (or remove the custom comparator) so description changes invalidate the memoized result. [logic error]Severity Level: Minor 🧹
Steps of Reproduction ✅
Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖