Skip to content

Commit

Permalink
chore(explore): Hide non-droppable metric and column list (#27717)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpark committed Apr 5, 2024
1 parent 9377227 commit eda304b
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
import { render, screen, waitFor } from 'spec/helpers/testing-library';
import { render, screen, waitFor, within } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import DatasourcePanel, {
IDatasource,
Expand All @@ -29,6 +29,11 @@ import {
} from 'src/explore/components/DatasourcePanel/fixtures';
import { DatasourceType } from '@superset-ui/core';
import DatasourceControl from 'src/explore/components/controls/DatasourceControl';
import ExploreContainer from '../ExploreContainer';
import {
DndColumnSelect,
DndMetricSelect,
} from '../controls/DndColumnSelectControl';

jest.mock(
'react-virtualized-auto-sizer',
Expand Down Expand Up @@ -83,6 +88,12 @@ const props: DatasourcePanelProps = {
width: 300,
};

const metricProps = {
savedMetrics: [],
columns: [],
onChange: jest.fn(),
};

const search = (value: string, input: HTMLElement) => {
userEvent.clear(input);
userEvent.type(input, value);
Expand All @@ -104,7 +115,13 @@ test('should display items in controls', async () => {
});

test('should render the metrics', async () => {
render(<DatasourcePanel {...props} />, { useRedux: true, useDnd: true });
render(
<ExploreContainer>
<DatasourcePanel {...props} />
<DndMetricSelect {...metricProps} />
</ExploreContainer>,
{ useRedux: true, useDnd: true },
);
const metricsNum = metrics.length;
metrics.forEach(metric =>
expect(screen.getByText(metric.metric_name)).toBeInTheDocument(),
Expand All @@ -115,7 +132,13 @@ test('should render the metrics', async () => {
});

test('should render the columns', async () => {
render(<DatasourcePanel {...props} />, { useRedux: true, useDnd: true });
render(
<ExploreContainer>
<DatasourcePanel {...props} />
<DndMetricSelect {...metricProps} />
</ExploreContainer>,
{ useRedux: true, useDnd: true },
);
const columnsNum = columns.length;
columns.forEach(col =>
expect(screen.getByText(col.column_name)).toBeInTheDocument(),
Expand All @@ -134,7 +157,13 @@ test('should render 0 search results', async () => {
});

test('should search and render matching columns', async () => {
render(<DatasourcePanel {...props} />, { useRedux: true, useDnd: true });
render(
<ExploreContainer>
<DatasourcePanel {...props} />
<DndMetricSelect {...metricProps} />
</ExploreContainer>,
{ useRedux: true, useDnd: true },
);
const searchInput = screen.getByPlaceholderText('Search Metrics & Columns');

search(columns[0].column_name, searchInput);
Expand All @@ -146,7 +175,13 @@ test('should search and render matching columns', async () => {
});

test('should search and render matching metrics', async () => {
render(<DatasourcePanel {...props} />, { useRedux: true, useDnd: true });
render(
<ExploreContainer>
<DatasourcePanel {...props} />
<DndMetricSelect {...metricProps} />
</ExploreContainer>,
{ useRedux: true, useDnd: true },
);
const searchInput = screen.getByPlaceholderText('Search Metrics & Columns');

search(metrics[0].metric_name, searchInput);
Expand Down Expand Up @@ -211,3 +246,41 @@ test('should not render a save dataset modal when datasource is not query or dat

expect(screen.queryByText(/create a dataset/i)).toBe(null);
});

test('should render only droppable metrics and columns', async () => {
const column1FilterProps = {
type: 'DndColumnSelect' as const,
name: 'Filter',
onChange: jest.fn(),
options: [{ column_name: columns[1].column_name }],
actions: { setControlValue: jest.fn() },
};
const column2FilterProps = {
type: 'DndColumnSelect' as const,
name: 'Filter',
onChange: jest.fn(),
options: [
{ column_name: columns[1].column_name },
{ column_name: columns[2].column_name },
],
actions: { setControlValue: jest.fn() },
};
const { getByTestId } = render(
<ExploreContainer>
<DatasourcePanel {...props} />
<DndColumnSelect {...column1FilterProps} />
<DndColumnSelect {...column2FilterProps} />
</ExploreContainer>,
{ useRedux: true, useDnd: true },
);
const selections = getByTestId('fieldSelections');
expect(
within(selections).queryByText(columns[0].column_name),
).not.toBeInTheDocument();
expect(
within(selections).queryByText(columns[1].column_name),
).toBeInTheDocument();
expect(
within(selections).queryByText(columns[2].column_name),
).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const mockData = {
onCollapseMetricsChange: jest.fn(),
collapseColumns: false,
onCollapseColumnsChange: jest.fn(),
hiddenMetricCount: 0,
hiddenColumnCount: 0,
};

test('renders each item accordingly', () => {
Expand Down Expand Up @@ -166,3 +168,32 @@ test('can collapse metrics and columns', () => {
);
expect(queryByText('Columns')).toBeInTheDocument();
});

test('shows ineligible items count', () => {
const hiddenColumnCount = 3;
const hiddenMetricCount = 1;
const dataWithHiddenItems = {
...mockData,
hiddenColumnCount,
hiddenMetricCount,
};
const { getByText, rerender } = render(
<DatasourcePanelItem index={1} data={dataWithHiddenItems} style={{}} />,
{ useDnd: true },
);
expect(
getByText(`${hiddenMetricCount} ineligible item(s) are hidden`),
).toBeInTheDocument();

const startIndexOfColumnSection = mockData.metricSlice.length + 3;
rerender(
<DatasourcePanelItem
index={startIndexOfColumnSection + 1}
data={dataWithHiddenItems}
style={{}}
/>,
);
expect(
getByText(`${hiddenColumnCount} ineligible item(s) are hidden`),
).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type Props = {
onCollapseMetricsChange: (collapse: boolean) => void;
collapseColumns: boolean;
onCollapseColumnsChange: (collapse: boolean) => void;
hiddenMetricCount: number;
hiddenColumnCount: number;
};
};

Expand Down Expand Up @@ -130,6 +132,19 @@ const SectionHeader = styled.span`
`}
`;

const Box = styled.div`
${({ theme }) => `
border: 1px ${theme.colors.grayscale.light4} solid;
border-radius: ${theme.gridUnit}px;
font-size: ${theme.typography.sizes.s}px;
padding: ${theme.gridUnit}px;
color: ${theme.colors.grayscale.light1};
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
`}
`;

const DatasourcePanelItem: React.FC<Props> = ({ index, style, data }) => {
const {
metricSlice: _metricSlice,
Expand All @@ -145,6 +160,8 @@ const DatasourcePanelItem: React.FC<Props> = ({ index, style, data }) => {
onCollapseMetricsChange,
collapseColumns,
onCollapseColumnsChange,
hiddenMetricCount,
hiddenColumnCount,
} = data;
const metricSlice = collapseMetrics ? [] : _metricSlice;

Expand All @@ -169,6 +186,7 @@ const DatasourcePanelItem: React.FC<Props> = ({ index, style, data }) => {
? onShowAllColumnsChange
: onShowAllMetricsChange;
const theme = useTheme();
const hiddenCount = isColumnSection ? hiddenColumnCount : hiddenMetricCount;

return (
<div
Expand All @@ -190,10 +208,27 @@ const DatasourcePanelItem: React.FC<Props> = ({ index, style, data }) => {
</SectionHeaderButton>
)}
{index === SUBTITLE_LINE && !collapsed && (
<div className="field-length">
{isColumnSection
? t(`Showing %s of %s`, columnSlice?.length, totalColumns)
: t(`Showing %s of %s`, metricSlice?.length, totalMetrics)}
<div
css={css`
display: flex;
gap: ${theme.gridUnit * 2}px;
justify-content: space-between;
align-items: baseline;
`}
>
<div
className="field-length"
css={css`
flex-shrink: 0;
`}
>
{isColumnSection
? t(`Showing %s of %s`, columnSlice?.length, totalColumns)
: t(`Showing %s of %s`, metricSlice?.length, totalMetrics)}
</div>
{hiddenCount > 0 && (
<Box>{t(`%s ineligible item(s) are hidden`, hiddenCount)}</Box>
)}
</div>
)}
{index > SUBTITLE_LINE && index < BOTTOM_LINE && (
Expand Down
Loading

0 comments on commit eda304b

Please sign in to comment.