Migrates DropdownButton component from Bootstrap to AntD (#13002)

This commit is contained in:
Michael S. Molina 2021-02-18 15:14:21 -03:00 committed by GitHub
parent 9489f0b8f4
commit 9335b9c983
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 91 deletions

View File

@ -38,7 +38,7 @@ describe('Test explore links', () => {
cy.visitChartByName('Growth Rate');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.get('button#query').click();
cy.get('div#query').click();
cy.get('span').contains('View query').parent().click();
cy.wait('@chartData').then(() => {
cy.get('code');

View File

@ -17,10 +17,9 @@
* under the License.
*/
import React from 'react';
import { mount } from 'enzyme';
import { mount, shallow } from 'enzyme';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { Menu } from 'src/common/components';
import ModalTrigger from 'src/components/ModalTrigger';
import { Dropdown, Menu } from 'src/common/components';
import { DisplayQueryButton } from 'src/explore/components/DisplayQueryButton';
describe('DisplayQueryButton', () => {
@ -43,14 +42,16 @@ describe('DisplayQueryButton', () => {
true,
);
});
it('renders a dropdown', () => {
it('renders a dropdown with 3 itens', () => {
const wrapper = mount(<DisplayQueryButton {...defaultProps} />, {
wrappingComponent: ThemeProvider,
wrappingComponentProps: {
theme: supersetTheme,
},
});
expect(wrapper.find(ModalTrigger)).toHaveLength(1);
expect(wrapper.find(Menu.Item)).toHaveLength(3);
const dropdown = wrapper.find(Dropdown);
const menu = shallow(<div>{dropdown.prop('overlay')}</div>);
const menuItems = menu.find(Menu.Item);
expect(menuItems).toHaveLength(3);
});
});

View File

@ -19,9 +19,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { styled } from '@superset-ui/core';
import { DropdownButton } from 'react-bootstrap';
import { Menu } from 'src/common/components';
import { styled, withTheme } from '@superset-ui/core';
import { Dropdown, Menu } from 'src/common/components';
import Icon from 'src/components/Icon';
const propTypes = {
id: PropTypes.string.isRequired,
@ -78,6 +78,7 @@ const MenuItem = styled(Menu.Item)`
class PopoverDropdown extends React.PureComponent {
constructor(props) {
super(props);
this.handleSelect = this.handleSelect.bind(this);
}
@ -86,28 +87,41 @@ class PopoverDropdown extends React.PureComponent {
}
render() {
const { id, value, options, renderButton, renderOption } = this.props;
const {
id,
value,
options,
renderButton,
renderOption,
theme,
} = this.props;
const selected = options.find(opt => opt.value === value);
return (
<DropdownButton
<Dropdown
id={id}
bsSize="small"
title={renderButton(selected)}
className="popover-dropdown"
trigger="click"
overlayStyle={{ zIndex: theme.zIndex.max }}
overlay={
<Menu onClick={this.handleSelect}>
{options.map(option => (
<MenuItem
id="menu-item"
key={option.value}
className={cx('dropdown-item', {
active: option.value === value,
})}
>
{renderOption(option)}
</MenuItem>
))}
</Menu>
}
>
<Menu onClick={this.handleSelect}>
{options.map(option => (
<MenuItem
key={option.value}
className={cx('dropdown-item', {
active: option.value === value,
})}
>
{renderOption(option)}
</MenuItem>
))}
</Menu>
</DropdownButton>
<div role="button" css={{ display: 'flex', alignItems: 'center' }}>
{renderButton(selected)}
<Icon name="caret-down" css={{ marginTop: 4 }} />
</div>
</Dropdown>
);
}
}
@ -115,4 +129,4 @@ class PopoverDropdown extends React.PureComponent {
PopoverDropdown.propTypes = propTypes;
PopoverDropdown.defaultProps = defaultProps;
export default PopoverDropdown;
export default withTheme(PopoverDropdown);

View File

@ -38,7 +38,9 @@ const defaultProps = {
menuItems: [],
isFocused: false,
shouldFocus: (event, container) =>
container && container.contains(event.target),
container?.contains(event.target) ||
event.target.id === 'menu-item' ||
event.target.parentNode?.id === 'menu-item',
style: null,
};

View File

@ -48,11 +48,11 @@
.dragdroppable-row .dashboard-component-header {
cursor: move;
}
}
.header-style-option {
font-weight: @font-weight-bold;
color: @almost-black;
}
.header-style-option {
font-weight: @font-weight-bold;
color: @almost-black;
}
.dashboard-header .dashboard-component-header {

View File

@ -66,13 +66,6 @@
background: @gray-light;
margin: 0 16px;
}
.popover-dropdown.btn {
border: none;
padding: 0;
font-size: inherit;
color: @almost-black;
}
}
/* the focus menu doesn't account for parent padding */
@ -88,7 +81,6 @@
left: -7px;
}
.popover-menu .popover-dropdown.btn,
.hover-dropdown .btn {
&:hover,
&:active,
@ -113,12 +105,6 @@
}
}
.popover-dropdown .caret {
/* without this the caret doesn't take up full width / is clipped */
width: auto;
border-top-color: transparent;
}
/* background style menu */
.background-style-option {
display: inline-block;

View File

@ -26,10 +26,9 @@ import markdownSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/mar
import sqlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql';
import jsonSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/json';
import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github';
import { DropdownButton } from 'react-bootstrap';
import { styled, t } from '@superset-ui/core';
import { Menu } from 'src/common/components';
import { Dropdown, Menu } from 'src/common/components';
import { getClientErrorObject } from '../../utils/getClientErrorObject';
import CopyToClipboard from '../../components/CopyToClipboard';
import { getChartDataRequest } from '../../chart/chartAction';
@ -75,7 +74,6 @@ export const DisplayQueryButton = props => {
const [sqlSupported] = useState(
datasource && datasource.split('__')[1] === 'table',
);
const [menuVisible, setMenuVisible] = useState(false);
const beforeOpen = resultType => {
setIsLoading(true);
@ -103,7 +101,6 @@ export const DisplayQueryButton = props => {
const handleMenuClick = ({ key, domEvent }) => {
const { chartHeight, slice, onOpenInEditor, latestQueryFormData } = props;
setMenuVisible(false);
switch (key) {
case MENU_KEYS.EDIT_PROPERTIES:
props.onOpenPropertiesModal();
@ -156,48 +153,47 @@ export const DisplayQueryButton = props => {
const { slice } = props;
return (
<DropdownButton
open={menuVisible}
noCaret
<Dropdown
trigger="click"
data-test="query-dropdown"
title={
<span>
<i className="fa fa-bars" />
&nbsp;
</span>
overlay={
<Menu onClick={handleMenuClick} selectable={false}>
{slice && (
<Menu.Item key={MENU_KEYS.EDIT_PROPERTIES}>
{t('Edit properties')}
</Menu.Item>
)}
<Menu.Item>
<ModalTrigger
triggerNode={
<span data-test="view-query-menu-item">{t('View query')}</span>
}
modalTitle={t('View query')}
beforeOpen={() => beforeOpen('query')}
modalBody={renderQueryModalBody()}
responsive
/>
</Menu.Item>
{sqlSupported && (
<Menu.Item key={MENU_KEYS.RUN_IN_SQL_LAB}>
{t('Run in SQL Lab')}
</Menu.Item>
)}
<Menu.Item key={MENU_KEYS.DOWNLOAD_AS_IMAGE}>
{t('Download as image')}
</Menu.Item>
</Menu>
}
bsSize="sm"
pullRight
id="query"
onToggle={setMenuVisible}
>
<Menu onClick={handleMenuClick} selectable={false}>
{slice && (
<Menu.Item key={MENU_KEYS.EDIT_PROPERTIES}>
{t('Edit properties')}
</Menu.Item>
)}
<Menu.Item>
<ModalTrigger
triggerNode={
<span data-test="view-query-menu-item">{t('View query')}</span>
}
modalTitle={t('View query')}
beforeOpen={() => beforeOpen('query')}
modalBody={renderQueryModalBody()}
responsive
/>
</Menu.Item>
{sqlSupported && (
<Menu.Item key={MENU_KEYS.RUN_IN_SQL_LAB}>
{t('Run in SQL Lab')}
</Menu.Item>
)}
<Menu.Item key={MENU_KEYS.DOWNLOAD_AS_IMAGE}>
{t('Download as image')}
</Menu.Item>
</Menu>
</DropdownButton>
<div
role="button"
id="query"
tabIndex={0}
className="btn btn-default btn-sm"
>
<i className="fa fa-bars" />
</div>
</Dropdown>
);
};

View File

@ -62,6 +62,11 @@
text-transform: uppercase;
}
.btn:focus,
.btn:active:focus {
outline: none;
}
.nav-tabs {
.dropdown-toggle.btn,
.btn-group.open .dropdown-toggle.btn {