fix(filters): improving the add filter/divider UI. (#31279)
This commit is contained in:
parent
cf5c770adc
commit
45815d8642
|
|
@ -263,7 +263,6 @@ describe('Native filters', () => {
|
|||
});
|
||||
|
||||
it('User can expand / retract native filter sidebar on a dashboard', () => {
|
||||
cy.get(nativeFilters.addFilterButton.button).should('not.exist');
|
||||
expandFilterOnLeftPanel();
|
||||
cy.get(nativeFilters.filterFromDashboardView.createFilterButton).should(
|
||||
'be.visible',
|
||||
|
|
|
|||
|
|
@ -243,11 +243,7 @@ export function enterNativeFilterEditModal(waitForDataset = true) {
|
|||
* @summary helper for adding new filter
|
||||
************************************************************************* */
|
||||
export function clickOnAddFilterInModal() {
|
||||
cy.get(nativeFilters.addFilterButton.button).first().click();
|
||||
return cy
|
||||
.get(nativeFilters.addFilterButton.dropdownItem)
|
||||
.contains('Filter')
|
||||
.click({ force: true });
|
||||
return cy.get(nativeFilters.modal.addNewFilterButton).click({ force: true });
|
||||
}
|
||||
|
||||
/** ************************************************************************
|
||||
|
|
|
|||
|
|
@ -334,10 +334,8 @@ export const nativeFilters = {
|
|||
},
|
||||
addFilter: dataTestLocator('add-filter-button'),
|
||||
defaultValueCheck: '.ant-checkbox-checked',
|
||||
},
|
||||
addFilterButton: {
|
||||
button: `.ant-modal-content [data-test="new-dropdown-icon"]`,
|
||||
dropdownItem: '.ant-dropdown-menu-item',
|
||||
addNewFilterButton: dataTestLocator('add-new-filter-button'),
|
||||
addNewDividerButton: dataTestLocator('add-new-divider-button'),
|
||||
},
|
||||
filtersPanel: {
|
||||
filterName: dataTestLocator('filters-config-modal__name-input'),
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
|||
return (
|
||||
<ButtonGroup
|
||||
css={css`
|
||||
display: flex;
|
||||
column-gap: ${theme.gridUnit * 1.5}px;
|
||||
margin-right: ${theme.gridUnit}px;
|
||||
& span {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { ReactNode } from 'react';
|
|||
export interface ButtonGroupProps {
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
expand?: boolean;
|
||||
}
|
||||
|
||||
export default function ButtonGroup(props: ButtonGroupProps) {
|
||||
|
|
@ -30,22 +31,28 @@ export default function ButtonGroup(props: ButtonGroupProps) {
|
|||
role="group"
|
||||
className={className}
|
||||
css={{
|
||||
'& :nth-of-type(1):not(:nth-last-of-type(1))': {
|
||||
display: 'flex',
|
||||
'& > :nth-of-type(1):not(:nth-last-of-type(1))': {
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
borderRight: 0,
|
||||
marginLeft: 0,
|
||||
},
|
||||
'& :not(:nth-of-type(1)):not(:nth-last-of-type(1))': {
|
||||
'& > :not(:nth-of-type(1)):not(:nth-last-of-type(1))': {
|
||||
borderRadius: 0,
|
||||
borderRight: 0,
|
||||
marginLeft: 0,
|
||||
},
|
||||
'& :nth-last-of-type(1):not(:nth-of-type(1))': {
|
||||
'& > :nth-last-of-type(1):not(:nth-of-type(1))': {
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
marginLeft: 0,
|
||||
},
|
||||
...(props.expand && {
|
||||
'& .superset-button': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import {
|
|||
LineChartOutlined,
|
||||
LoadingOutlined,
|
||||
MonitorOutlined,
|
||||
PicCenterOutlined,
|
||||
PlusCircleOutlined,
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
|
|
@ -106,6 +107,7 @@ const AntdIcons = {
|
|||
LineChartOutlined,
|
||||
LoadingOutlined,
|
||||
MonitorOutlined,
|
||||
PicCenterOutlined,
|
||||
PlusCircleOutlined,
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
|
|
|
|||
|
|
@ -98,9 +98,7 @@ test('remove filter', async () => {
|
|||
test('add filter', async () => {
|
||||
defaultRender();
|
||||
// First trash icon
|
||||
const addButton = screen.getByText('Add filters and dividers')!;
|
||||
fireEvent.mouseOver(addButton);
|
||||
const addFilterButton = await screen.findByText('Filter');
|
||||
const addFilterButton = await screen.findByText('Add Filter');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent(
|
||||
|
|
@ -116,9 +114,7 @@ test('add filter', async () => {
|
|||
|
||||
test('add divider', async () => {
|
||||
defaultRender();
|
||||
const addButton = screen.getByText('Add filters and dividers')!;
|
||||
fireEvent.mouseOver(addButton);
|
||||
const addFilterButton = await screen.findByText('Divider');
|
||||
const addFilterButton = await screen.findByText('Add Divider');
|
||||
await act(async () => {
|
||||
fireEvent(
|
||||
addFilterButton,
|
||||
|
|
@ -151,18 +147,18 @@ test('filter container should scroll to bottom when adding items', async () => {
|
|||
|
||||
defaultRender(state, props);
|
||||
|
||||
const addButton = screen.getByText('Add filters and dividers')!;
|
||||
fireEvent.mouseOver(addButton);
|
||||
|
||||
const addFilterButton = await screen.findByText('Filter');
|
||||
const addFilterButton = await screen.findByText('Add Filter');
|
||||
// add enough filters to make it scroll in the next expectation.
|
||||
await act(async () => {
|
||||
fireEvent(
|
||||
addFilterButton,
|
||||
new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}),
|
||||
);
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
fireEvent(
|
||||
addFilterButton,
|
||||
new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const containerElement = screen.getByTestId('filter-title-container');
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@
|
|||
import { useRef, FC } from 'react';
|
||||
|
||||
import { NativeFilterType, styled, t, useTheme } from '@superset-ui/core';
|
||||
import { AntdDropdown } from 'src/components';
|
||||
import { MainNav as Menu } from 'src/components/Menu';
|
||||
import { Button } from 'src/components';
|
||||
import Icons from 'src/components/Icons';
|
||||
|
||||
import FilterTitleContainer from './FilterTitleContainer';
|
||||
import { FilterRemoval } from './types';
|
||||
|
||||
|
|
@ -37,27 +38,14 @@ interface Props {
|
|||
erroredFilters: string[];
|
||||
}
|
||||
|
||||
const StyledAddBox = styled.div`
|
||||
${({ theme }) => `
|
||||
cursor: pointer;
|
||||
margin: ${theme.gridUnit * 4}px;
|
||||
color: ${theme.colors.primary.base};
|
||||
&:hover {
|
||||
color: ${theme.colors.primary.dark1};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
const TabsContainer = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${({ theme }) => theme.gridUnit * 3}px;
|
||||
padding-top: 2px;
|
||||
`;
|
||||
|
||||
const options = [
|
||||
{ label: t('Filter'), type: NativeFilterType.NativeFilter },
|
||||
{ label: t('Divider'), type: NativeFilterType.Divider },
|
||||
];
|
||||
|
||||
const FilterTitlePane: FC<Props> = ({
|
||||
getFilterTitle,
|
||||
onChange,
|
||||
|
|
@ -70,9 +58,10 @@ const FilterTitlePane: FC<Props> = ({
|
|||
removedFilters,
|
||||
erroredFilters,
|
||||
}) => {
|
||||
const filtersContainerRef = useRef<HTMLDivElement>(null);
|
||||
const theme = useTheme();
|
||||
|
||||
const filtersContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleOnAdd = (type: NativeFilterType) => {
|
||||
onAdd(type);
|
||||
setTimeout(() => {
|
||||
|
|
@ -88,33 +77,12 @@ const FilterTitlePane: FC<Props> = ({
|
|||
});
|
||||
}, 0);
|
||||
};
|
||||
const menu = (
|
||||
<Menu mode="horizontal">
|
||||
{options.map(item => (
|
||||
<Menu.Item onClick={() => handleOnAdd(item.type)}>
|
||||
{item.label}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
);
|
||||
return (
|
||||
<TabsContainer>
|
||||
<AntdDropdown
|
||||
overlay={menu}
|
||||
arrow
|
||||
placement="topLeft"
|
||||
trigger={['hover']}
|
||||
>
|
||||
<StyledAddBox>
|
||||
<div data-test="new-dropdown-icon" className="fa fa-plus" />{' '}
|
||||
<span>{t('Add filters and dividers')}</span>
|
||||
</StyledAddBox>
|
||||
</AntdDropdown>
|
||||
<div
|
||||
css={{
|
||||
height: '100%',
|
||||
overflowY: 'auto',
|
||||
marginLeft: theme.gridUnit * 3,
|
||||
}}
|
||||
>
|
||||
<FilterTitleContainer
|
||||
|
|
@ -130,6 +98,33 @@ const FilterTitlePane: FC<Props> = ({
|
|||
restoreFilter={restoreFilter}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-around',
|
||||
alignItems: 'flex-start',
|
||||
paddingTop: theme.gridUnit * 3,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
buttonSize="default"
|
||||
buttonStyle="secondary"
|
||||
icon={<Icons.Filter iconSize="m" />}
|
||||
data-test="add-new-filter-button"
|
||||
onClick={() => handleOnAdd(NativeFilterType.NativeFilter)}
|
||||
>
|
||||
{t('Add Filter')}
|
||||
</Button>
|
||||
<Button
|
||||
buttonSize="default"
|
||||
buttonStyle="secondary"
|
||||
icon={<Icons.PicCenterOutlined iconSize="m" />}
|
||||
data-test="add-new-divider-button"
|
||||
onClick={() => handleOnAdd(NativeFilterType.Divider)}
|
||||
>
|
||||
{t('Add Divider')}
|
||||
</Button>
|
||||
</div>
|
||||
</TabsContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,13 +88,11 @@ describe('createNewOnOpen', () => {
|
|||
|
||||
test('shows correct alert message for unsaved filters', async () => {
|
||||
const onCancel = jest.fn();
|
||||
const { getByRole, getByTestId, findByRole } = setup({
|
||||
const { getByRole, getByTestId } = setup({
|
||||
onCancel,
|
||||
createNewOnOpen: false,
|
||||
});
|
||||
fireEvent.mouseOver(getByTestId('new-dropdown-icon'));
|
||||
const addFilterButton = await findByRole('menuitem', { name: 'Filter' });
|
||||
fireEvent.click(addFilterButton);
|
||||
fireEvent.click(getByTestId('add-new-filter-button'));
|
||||
fireEvent.click(getByRole('button', { name: 'Cancel' }));
|
||||
expect(onCancel).toHaveBeenCalledTimes(0);
|
||||
expect(getByRole('alert')).toBeInTheDocument();
|
||||
|
|
|
|||
Loading…
Reference in New Issue