This is an automated email from the ASF dual-hosted git repository.
jli 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 f60c82e4a60 fix: charts row limit warning is missing for server
(#37112)
f60c82e4a60 is described below
commit f60c82e4a6045245d1647f608ffc779d9bf795ab
Author: Ramiro Aquino Romero <[email protected]>
AuthorDate: Mon Feb 2 19:49:31 2026 -0400
fix: charts row limit warning is missing for server (#37112)
---
.../components/SliceHeader/SliceHeader.test.tsx | 189 ++++++++++++++++++++-
.../src/dashboard/components/SliceHeader/index.tsx | 20 ++-
.../src/explore/components/ChartPills.tsx | 20 ++-
.../explore/components/ExploreChartPanel/index.tsx | 1 +
4 files changed, 218 insertions(+), 12 deletions(-)
diff --git
a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
index b7bc53eb5a1..14007f7dda0 100644
---
a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
+++
b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
@@ -569,22 +569,47 @@ test('Should render RowCountLabel when row limit is hit,
and hide it otherwise',
const props = createProps({
formData: {
...createProps().formData,
+ viz_type: VizType.Table,
row_limit: 10,
},
+ slice: {
+ ...createProps().slice,
+ viz_type: VizType.Table,
+ form_data: {
+ ...createProps().slice.form_data,
+ viz_type: VizType.Table,
+ row_limit: 10,
+ },
+ },
});
const rowCountState = {
...initialState,
charts: {
[props.slice.slice_id]: {
+ id: MOCKED_CHART_ID,
+ chartStatus: 'rendered',
queriesResponse: [
{
sql_rowcount: 10,
+ data: Array(10).fill({}),
},
],
},
},
};
+ const mockUseUiConfig = useUiConfig as jest.MockedFunction<
+ typeof useUiConfig
+ >;
+ mockUseUiConfig.mockReturnValue({
+ hideTitle: false,
+ hideTab: false,
+ hideNav: false,
+ hideChartControls: false,
+ emitDataMasks: false,
+ showRowLimitWarning: true,
+ });
+
const { rerender } = render(<SliceHeader {...props} />, {
useRedux: true,
useRouter: true,
@@ -592,6 +617,7 @@ test('Should render RowCountLabel when row limit is hit,
and hide it otherwise',
});
expect(screen.getByTestId('warning')).toBeInTheDocument();
+
rerender(
<SliceHeader
{...props}
@@ -600,11 +626,25 @@ test('Should render RowCountLabel when row limit is hit,
and hide it otherwise',
);
expect(screen.queryByTestId('warning')).not.toBeInTheDocument();
+
+ mockUseUiConfig.mockRestore();
});
-test('Should hide RowCountLabel in embedded by default', () => {
+test('Should hide warning in embedded by default for non-table charts', () => {
const mockIsEmbedded = isEmbedded as jest.MockedFunction<typeof isEmbedded>;
+ const mockUseUiConfig = useUiConfig as jest.MockedFunction<
+ typeof useUiConfig
+ >;
+
mockIsEmbedded.mockReturnValue(true);
+ mockUseUiConfig.mockReturnValue({
+ hideTitle: false,
+ hideTab: false,
+ hideNav: false,
+ hideChartControls: false,
+ emitDataMasks: false,
+ showRowLimitWarning: false,
+ });
const props = createProps({
formData: {
@@ -632,17 +672,16 @@ test('Should hide RowCountLabel in embedded by default',
() => {
});
expect(screen.queryByTestId('warning')).not.toBeInTheDocument();
+ expect(screen.queryByTestId('row-count-label')).not.toBeInTheDocument();
mockIsEmbedded.mockRestore();
+ mockUseUiConfig.mockRestore();
});
-test('Should show RowCountLabel in embedded when uiConfig.showRowLimitWarning
is true', () => {
- const mockIsEmbedded = isEmbedded as jest.MockedFunction<typeof isEmbedded>;
+test('Should show row count badge for table chart without server pagination',
() => {
const mockUseUiConfig = useUiConfig as jest.MockedFunction<
typeof useUiConfig
>;
-
- mockIsEmbedded.mockReturnValue(true);
mockUseUiConfig.mockReturnValue({
hideTitle: false,
hideTab: false,
@@ -655,30 +694,164 @@ test('Should show RowCountLabel in embedded when
uiConfig.showRowLimitWarning is
const props = createProps({
formData: {
...createProps().formData,
+ viz_type: VizType.Table,
row_limit: 10,
},
+ slice: {
+ ...createProps().slice,
+ form_data: {
+ ...createProps().slice.form_data,
+ viz_type: VizType.Table,
+ row_limit: 10,
+ },
+ viz_type: VizType.Table,
+ },
});
- const rowCountState = {
+ const tableState = {
+ ...initialState,
+ charts: {
+ [props.slice.slice_id]: {
+ id: MOCKED_CHART_ID,
+ chartStatus: 'rendered',
+ queriesResponse: [
+ {
+ sql_rowcount: 50,
+ data: [],
+ },
+ ],
+ },
+ },
+ };
+
+ render(<SliceHeader {...props} />, {
+ useRedux: true,
+ useRouter: true,
+ initialState: tableState,
+ });
+
+ expect(screen.getByTestId('warning')).toBeInTheDocument();
+
+ mockUseUiConfig.mockRestore();
+});
+
+test('Should show row count warning for table chart with server pagination
when limit is reached', () => {
+ const props = createProps({
+ formData: {
+ ...createProps().formData,
+ viz_type: VizType.Table,
+ row_limit: 10,
+ server_pagination: true,
+ },
+ slice: {
+ ...createProps().slice,
+ form_data: {
+ ...createProps().slice.form_data,
+ viz_type: VizType.Table,
+ row_limit: 10,
+ server_pagination: true,
+ },
+ viz_type: VizType.Table,
+ },
+ });
+ const tableWithPaginationState = {
...initialState,
charts: {
[props.slice.slice_id]: {
+ id: MOCKED_CHART_ID,
+ chartStatus: 'rendered',
queriesResponse: [
{
sql_rowcount: 10,
+ data: Array(10).fill({}),
+ },
+ {
+ data: [{ rowcount: 50 }],
},
],
},
},
};
+ const mockUseUiConfig = useUiConfig as jest.MockedFunction<
+ typeof useUiConfig
+ >;
+ mockUseUiConfig.mockReturnValue({
+ hideTitle: false,
+ hideTab: false,
+ hideNav: false,
+ hideChartControls: false,
+ emitDataMasks: false,
+ showRowLimitWarning: true,
+ });
+
render(<SliceHeader {...props} />, {
useRedux: true,
useRouter: true,
- initialState: rowCountState,
+ initialState: tableWithPaginationState,
});
expect(screen.getByTestId('warning')).toBeInTheDocument();
- mockIsEmbedded.mockRestore();
+ mockUseUiConfig.mockRestore();
+});
+
+test('Should NOT show row count warning for table chart with server pagination
when limit is NOT reached', () => {
+ const props = createProps({
+ formData: {
+ ...createProps().formData,
+ viz_type: VizType.Table,
+ row_limit: 100,
+ server_pagination: true,
+ },
+ slice: {
+ ...createProps().slice,
+ form_data: {
+ ...createProps().slice.form_data,
+ viz_type: VizType.Table,
+ row_limit: 100,
+ server_pagination: true,
+ },
+ viz_type: VizType.Table,
+ },
+ });
+ const tableWithPaginationState = {
+ ...initialState,
+ charts: {
+ [props.slice.slice_id]: {
+ id: MOCKED_CHART_ID,
+ chartStatus: 'rendered',
+ queriesResponse: [
+ {
+ sql_rowcount: 10,
+ data: Array(10).fill({}),
+ },
+ {
+ data: [{ rowcount: 30 }],
+ },
+ ],
+ },
+ },
+ };
+
+ const mockUseUiConfig = useUiConfig as jest.MockedFunction<
+ typeof useUiConfig
+ >;
+ mockUseUiConfig.mockReturnValue({
+ hideTitle: false,
+ hideTab: false,
+ hideNav: false,
+ hideChartControls: false,
+ emitDataMasks: false,
+ showRowLimitWarning: true,
+ });
+
+ render(<SliceHeader {...props} />, {
+ useRedux: true,
+ useRouter: true,
+ initialState: tableWithPaginationState,
+ });
+
+ expect(screen.queryByTestId('warning')).not.toBeInTheDocument();
+
mockUseUiConfig.mockRestore();
});
diff --git a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
index 4e76ec6fe61..a0a6f702a4a 100644
--- a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
+++ b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
@@ -190,12 +190,26 @@ const SliceHeader = forwardRef<HTMLDivElement,
SliceHeaderProps>(
state => state.charts[slice.slice_id].queriesResponse?.[0],
);
+ const secondQueryResponse = useSelector<RootState, QueryData | undefined>(
+ state => state.charts[slice.slice_id].queriesResponse?.[1],
+ );
+
const theme = useTheme();
- const rowLimit = Number(formData.row_limit || -1);
- const sqlRowCount = Number(firstQueryResponse?.sql_rowcount || 0);
+ const rowLimit = Number(formData.row_limit ?? 0);
+
+ const isTableChart = formData.viz_type === 'table';
+ const countFromSecondQuery =
+ isTableChart && secondQueryResponse?.data?.[0]?.rowcount;
+
+ const sqlRowCount =
+ countFromSecondQuery != null
+ ? countFromSecondQuery
+ : Number(firstQueryResponse?.sql_rowcount ?? 0);
const canExplore = !editMode && supersetCanExplore;
+ const showRowLimitWarning =
+ shouldShowRowLimitWarning && sqlRowCount >= rowLimit && rowLimit > 0;
useEffect(() => {
const headerElement = headerRef.current;
@@ -304,7 +318,7 @@ const SliceHeader = forwardRef<HTMLDivElement,
SliceHeaderProps>(
<FiltersBadge chartId={slice.slice_id} />
)}
- {shouldShowRowLimitWarning && sqlRowCount === rowLimit && (
+ {showRowLimitWarning && (
<RowCountLabel
rowcount={sqlRowCount}
limit={rowLimit}
diff --git a/superset-frontend/src/explore/components/ChartPills.tsx
b/superset-frontend/src/explore/components/ChartPills.tsx
index 42b337cfd71..a3d26de0a57 100644
--- a/superset-frontend/src/explore/components/ChartPills.tsx
+++ b/superset-frontend/src/explore/components/ChartPills.tsx
@@ -43,6 +43,11 @@ export type ChartPillsProps = {
refreshCachedQuery: () => void;
rowLimit?: string | number;
hideRowCount?: boolean;
+ formData?: {
+ viz_type?: string;
+ server_pagination?: boolean;
+ [key: string]: unknown;
+ };
};
export const ChartPills = forwardRef(
@@ -55,12 +60,25 @@ export const ChartPills = forwardRef(
refreshCachedQuery,
rowLimit,
hideRowCount = false,
+ formData,
}: ChartPillsProps,
ref: RefObject<HTMLDivElement>,
) => {
const isLoading = chartStatus === 'loading';
const firstQueryResponse = queriesResponse?.[0];
+ // For table charts with server pagination, check second query for total
count
+ const isTableChart = formData?.viz_type === 'table';
+ const hasCountQuery = queriesResponse && queriesResponse.length > 1;
+ const countFromSecondQuery = hasCountQuery
+ ? queriesResponse[1]?.data?.[0]?.rowcount
+ : null;
+
+ const actualRowCount =
+ isTableChart && countFromSecondQuery != null
+ ? countFromSecondQuery
+ : Number(firstQueryResponse?.sql_rowcount ?? 0);
+
return (
<div ref={ref}>
<div
@@ -72,7 +90,7 @@ export const ChartPills = forwardRef(
>
{!isLoading && !hideRowCount && firstQueryResponse && (
<RowCountLabel
- rowcount={Number(firstQueryResponse.sql_rowcount) || 0}
+ rowcount={actualRowCount}
limit={Number(rowLimit ?? 0)}
/>
)}
diff --git
a/superset-frontend/src/explore/components/ExploreChartPanel/index.tsx
b/superset-frontend/src/explore/components/ExploreChartPanel/index.tsx
index c55fe306bff..9b24f282c0e 100644
--- a/superset-frontend/src/explore/components/ExploreChartPanel/index.tsx
+++ b/superset-frontend/src/explore/components/ExploreChartPanel/index.tsx
@@ -397,6 +397,7 @@ const ExploreChartPanel = ({
formData?.matrixify_enable_vertical_layout === true ||
formData?.matrixify_enable_horizontal_layout === true
}
+ formData={formData}
/>
</ChartHeaderExtension>
{renderChart()}