From 9335b9c98303af17b6f9ae70cbb6d4075c863387 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Thu, 18 Feb 2021 15:14:21 -0300 Subject: [PATCH] Migrates DropdownButton component from Bootstrap to AntD (#13002) --- .../cypress/integration/explore/link.test.ts | 2 +- .../components/DisplayQueryButton_spec.jsx | 13 +-- .../components/menu/PopoverDropdown.jsx | 58 ++++++++----- .../components/menu/WithPopoverMenu.jsx | 4 +- .../stylesheets/components/header.less | 8 +- .../dashboard/stylesheets/popover-menu.less | 14 ---- .../explore/components/DisplayQueryButton.jsx | 82 +++++++++---------- .../stylesheets/less/cosmo/bootswatch.less | 5 ++ 8 files changed, 95 insertions(+), 91 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/explore/link.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/link.test.ts index f825fe01d09..cab2074625f 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/link.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/link.test.ts @@ -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'); diff --git a/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx b/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx index 263656a6a9c..6a6757142fb 100644 --- a/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx +++ b/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx @@ -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(, { 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(
{dropdown.prop('overlay')}
); + const menuItems = menu.find(Menu.Item); + expect(menuItems).toHaveLength(3); }); }); diff --git a/superset-frontend/src/dashboard/components/menu/PopoverDropdown.jsx b/superset-frontend/src/dashboard/components/menu/PopoverDropdown.jsx index daad642906c..d67cd3836bb 100644 --- a/superset-frontend/src/dashboard/components/menu/PopoverDropdown.jsx +++ b/superset-frontend/src/dashboard/components/menu/PopoverDropdown.jsx @@ -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 ( - + {options.map(option => ( + + {renderOption(option)} + + ))} + + } > - - {options.map(option => ( - - {renderOption(option)} - - ))} - - +
+ {renderButton(selected)} + +
+ ); } } @@ -115,4 +129,4 @@ class PopoverDropdown extends React.PureComponent { PopoverDropdown.propTypes = propTypes; PopoverDropdown.defaultProps = defaultProps; -export default PopoverDropdown; +export default withTheme(PopoverDropdown); diff --git a/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx b/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx index eb439011577..dcd8dcfdd21 100644 --- a/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx +++ b/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx @@ -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, }; diff --git a/superset-frontend/src/dashboard/stylesheets/components/header.less b/superset-frontend/src/dashboard/stylesheets/components/header.less index ab4a2a4dcde..75713782614 100644 --- a/superset-frontend/src/dashboard/stylesheets/components/header.less +++ b/superset-frontend/src/dashboard/stylesheets/components/header.less @@ -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 { diff --git a/superset-frontend/src/dashboard/stylesheets/popover-menu.less b/superset-frontend/src/dashboard/stylesheets/popover-menu.less index 5ab2b873fcb..4abc4949936 100644 --- a/superset-frontend/src/dashboard/stylesheets/popover-menu.less +++ b/superset-frontend/src/dashboard/stylesheets/popover-menu.less @@ -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; diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 97b2d1a5e19..16bbf1d51a7 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -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 ( - - -   - + overlay={ + + {slice && ( + + {t('Edit properties')} + + )} + + {t('View query')} + } + modalTitle={t('View query')} + beforeOpen={() => beforeOpen('query')} + modalBody={renderQueryModalBody()} + responsive + /> + + {sqlSupported && ( + + {t('Run in SQL Lab')} + + )} + + {t('Download as image')} + + } - bsSize="sm" - pullRight - id="query" - onToggle={setMenuVisible} > - - {slice && ( - - {t('Edit properties')} - - )} - - {t('View query')} - } - modalTitle={t('View query')} - beforeOpen={() => beforeOpen('query')} - modalBody={renderQueryModalBody()} - responsive - /> - - {sqlSupported && ( - - {t('Run in SQL Lab')} - - )} - - {t('Download as image')} - - - +
+ +
+ ); }; diff --git a/superset-frontend/stylesheets/less/cosmo/bootswatch.less b/superset-frontend/stylesheets/less/cosmo/bootswatch.less index b9902f689cb..26c44bdaa34 100644 --- a/superset-frontend/stylesheets/less/cosmo/bootswatch.less +++ b/superset-frontend/stylesheets/less/cosmo/bootswatch.less @@ -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 {