mirror of
https://github.com/apache/superset.git
synced 2024-09-17 19:19:38 -04:00
refactor: Use Antd Dropdown instead of react-bootstrap in DatasourceControl (#11395)
* Create Tooltip component * Refactor DatasourceControl * Bug fix * Lint fix * E2E test fix * Move menu item keys to constants * Remove LESS file * Test fix * Test fix * Lint fix
This commit is contained in:
parent
6f69212f28
commit
ad88a06d61
@ -34,13 +34,13 @@ describe('Datasource control', () => {
|
|||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||||
|
|
||||||
cy.get('#datasource_menu').click();
|
cy.get('[data-test="datasource-menu-trigger"]').click();
|
||||||
|
|
||||||
cy.get('script').then(nodes => {
|
cy.get('script').then(nodes => {
|
||||||
numScripts = nodes.length;
|
numScripts = nodes.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('a').contains('Edit Dataset').click();
|
cy.get('[data-test="edit-dataset"]').click();
|
||||||
|
|
||||||
// should load additional scripts for the modal
|
// should load additional scripts for the modal
|
||||||
cy.get('script').then(nodes => {
|
cy.get('script').then(nodes => {
|
||||||
@ -65,8 +65,8 @@ describe('Datasource control', () => {
|
|||||||
.focus()
|
.focus()
|
||||||
.type(newMetricName, { force: true });
|
.type(newMetricName, { force: true });
|
||||||
// delete metric
|
// delete metric
|
||||||
cy.get('#datasource_menu').click();
|
cy.get('[data-test="datasource-menu-trigger"]').click();
|
||||||
cy.get('a').contains('Edit Dataset').click();
|
cy.get('[data-test="edit-dataset"]').click();
|
||||||
cy.get('.modal-content').within(() => {
|
cy.get('.modal-content').within(() => {
|
||||||
cy.get('a[role="tab"]').contains('Metrics').click();
|
cy.get('a[role="tab"]').contains('Metrics').click();
|
||||||
});
|
});
|
||||||
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import configureStore from 'redux-mock-store';
|
import configureStore from 'redux-mock-store';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { MenuItem } from 'react-bootstrap';
|
import { Menu } from 'src/common/components';
|
||||||
import DatasourceModal from 'src/datasource/DatasourceModal';
|
import DatasourceModal from 'src/datasource/DatasourceModal';
|
||||||
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
||||||
import DatasourceControl from 'src/explore/components/controls/DatasourceControl';
|
import DatasourceControl from 'src/explore/components/controls/DatasourceControl';
|
||||||
@ -72,17 +72,23 @@ describe('DatasourceControl', () => {
|
|||||||
|
|
||||||
it('show or hide Edit Datasource option', () => {
|
it('show or hide Edit Datasource option', () => {
|
||||||
let wrapper = setup();
|
let wrapper = setup();
|
||||||
expect(wrapper.find('#datasource_menu')).toExist();
|
expect(wrapper.find('[data-test="datasource-menu"]')).toExist();
|
||||||
expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength(
|
let menuWrapper = shallow(
|
||||||
3,
|
<div>
|
||||||
|
{wrapper.find('[data-test="datasource-menu"]').prop('overlay')}
|
||||||
|
</div>,
|
||||||
);
|
);
|
||||||
|
expect(menuWrapper.find(Menu.Item)).toHaveLength(3);
|
||||||
|
|
||||||
wrapper = setup({
|
wrapper = setup({
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
});
|
});
|
||||||
expect(wrapper.find('#datasource_menu')).toExist();
|
expect(wrapper.find('[data-test="datasource-menu"]')).toExist();
|
||||||
expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength(
|
menuWrapper = shallow(
|
||||||
2,
|
<div>
|
||||||
|
{wrapper.find('[data-test="datasource-menu"]').prop('overlay')}
|
||||||
|
</div>,
|
||||||
);
|
);
|
||||||
|
expect(menuWrapper.find(Menu.Item)).toHaveLength(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,33 +16,12 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
@import '../../../../stylesheets/less/variables.less';
|
import React from 'react';
|
||||||
|
import { Tooltip as BaseTooltip } from 'src/common/components';
|
||||||
|
import { TooltipProps } from 'antd/lib/tooltip';
|
||||||
|
|
||||||
#datasource_menu {
|
const Tooltip = (props: TooltipProps) => (
|
||||||
border-radius: @border-radius-normal;
|
<BaseTooltip overlayStyle={{ fontSize: '12px' }} {...props} />
|
||||||
padding: 0px;
|
);
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#datasource_menu .caret {
|
export default Tooltip;
|
||||||
position: relative;
|
|
||||||
padding-right: 8px;
|
|
||||||
margin-left: 4px;
|
|
||||||
color: @lightest;
|
|
||||||
top: -8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#datasource_menu .caret {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#datasource_menu:hover {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.DatasourceControl svg {
|
|
||||||
vertical-align: middle;
|
|
||||||
color: @brand-primary;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.DatasourceControl .angle {
|
|
||||||
color: @brand-primary;
|
|
||||||
}
|
|
@ -19,12 +19,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { withKnobs, boolean, select } from '@storybook/addon-knobs';
|
import { withKnobs, boolean, select } from '@storybook/addon-knobs';
|
||||||
|
import Button from 'src/components/Button';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import Tabs, { EditableTabs } from './Tabs';
|
import Tabs, { EditableTabs } from './Tabs';
|
||||||
import AntdPopover from './Popover';
|
import AntdPopover from './Popover';
|
||||||
|
import AntdTooltip from './Tooltip';
|
||||||
import { Menu } from '.';
|
import { Menu } from '.';
|
||||||
import { Dropdown } from './Dropdown';
|
import { Dropdown } from './Dropdown';
|
||||||
import Button from '../../components/Button';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Common Components',
|
title: 'Common Components',
|
||||||
@ -146,3 +147,31 @@ export const Popover = () => (
|
|||||||
<Button>TRIGGER</Button>
|
<Button>TRIGGER</Button>
|
||||||
</AntdPopover>
|
</AntdPopover>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const Tooltip = () => (
|
||||||
|
<AntdTooltip
|
||||||
|
title="This is a Tooltip"
|
||||||
|
trigger={select('Trigger', ['click', 'hover', 'focus'], 'click')}
|
||||||
|
placement={select(
|
||||||
|
'Placement',
|
||||||
|
[
|
||||||
|
'topLeft',
|
||||||
|
'top',
|
||||||
|
'topRight',
|
||||||
|
'leftTop',
|
||||||
|
'left',
|
||||||
|
'leftBottom',
|
||||||
|
'rightTop',
|
||||||
|
'right',
|
||||||
|
'rightBottom',
|
||||||
|
'bottomLeft',
|
||||||
|
'bottom',
|
||||||
|
'bottomRight',
|
||||||
|
],
|
||||||
|
'topLeft',
|
||||||
|
)}
|
||||||
|
arrowPointAtCenter={boolean('Arrow point at center', false)}
|
||||||
|
>
|
||||||
|
<Button>A button with tooltip</Button>
|
||||||
|
</AntdTooltip>
|
||||||
|
);
|
||||||
|
@ -18,28 +18,18 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import { Col, Collapse, Row, Well } from 'react-bootstrap';
|
||||||
Col,
|
|
||||||
Collapse,
|
|
||||||
DropdownButton,
|
|
||||||
MenuItem,
|
|
||||||
OverlayTrigger,
|
|
||||||
Row,
|
|
||||||
Tooltip,
|
|
||||||
Well,
|
|
||||||
} from 'react-bootstrap';
|
|
||||||
import { t, styled } from '@superset-ui/core';
|
import { t, styled } from '@superset-ui/core';
|
||||||
import { ColumnOption, MetricOption } from '@superset-ui/chart-controls';
|
import { ColumnOption, MetricOption } from '@superset-ui/chart-controls';
|
||||||
|
|
||||||
import TooltipWrapper from 'src/components/TooltipWrapper';
|
import { Dropdown, Menu } from 'src/common/components';
|
||||||
|
import Tooltip from 'src/common/components/Tooltip';
|
||||||
import Icon from 'src/components/Icon';
|
import Icon from 'src/components/Icon';
|
||||||
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
||||||
import DatasourceModal from 'src/datasource/DatasourceModal';
|
import DatasourceModal from 'src/datasource/DatasourceModal';
|
||||||
import Label from 'src/components/Label';
|
import Label from 'src/components/Label';
|
||||||
|
|
||||||
import ControlHeader from '../ControlHeader';
|
import ControlHeader from '../ControlHeader';
|
||||||
import './DatasourceControl.less';
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
actions: PropTypes.object.isRequired,
|
actions: PropTypes.object.isRequired,
|
||||||
@ -58,19 +48,30 @@ const defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Styles = styled.div`
|
const Styles = styled.div`
|
||||||
#datasource_menu {
|
.ant-dropdown-trigger {
|
||||||
margin-left: ${({ theme }) => theme.gridUnit}px;
|
margin-left: ${({ theme }) => theme.gridUnit}px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
&:active {
|
&:active {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group .open .dropdown-toggle {
|
.btn-group .open .dropdown-toggle {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
&.button-default {
|
&.button-default {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.angle {
|
||||||
|
color: ${({ theme }) => theme.colors.primary.base};
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.datasource-modal-trigger {
|
||||||
|
color: ${({ theme }) => theme.colors.primary.base};
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +85,10 @@ const ColumnsCol = styled(Col)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const CHANGE_DATASET = 'change_dataset';
|
||||||
|
const EXPLORE_IN_SQL_LAB = 'explore_in_sql_lab';
|
||||||
|
const EDIT_DATASET = 'edit_dataset';
|
||||||
|
|
||||||
class DatasourceControl extends React.PureComponent {
|
class DatasourceControl extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -98,6 +103,7 @@ class DatasourceControl extends React.PureComponent {
|
|||||||
this.toggleEditDatasourceModal = this.toggleEditDatasourceModal.bind(this);
|
this.toggleEditDatasourceModal = this.toggleEditDatasourceModal.bind(this);
|
||||||
this.toggleShowDatasource = this.toggleShowDatasource.bind(this);
|
this.toggleShowDatasource = this.toggleShowDatasource.bind(this);
|
||||||
this.renderDatasource = this.renderDatasource.bind(this);
|
this.renderDatasource = this.renderDatasource.bind(this);
|
||||||
|
this.handleMenuItemClick = this.handleMenuItemClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDatasourceSave(datasource) {
|
onDatasourceSave(datasource) {
|
||||||
@ -125,6 +131,15 @@ class DatasourceControl extends React.PureComponent {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleMenuItemClick({ key }) {
|
||||||
|
if (key === CHANGE_DATASET) {
|
||||||
|
this.toggleChangeDatasourceModal();
|
||||||
|
}
|
||||||
|
if (key === EDIT_DATASET) {
|
||||||
|
this.toggleEditDatasourceModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderDatasource() {
|
renderDatasource() {
|
||||||
const { datasource } = this.props;
|
const { datasource } = this.props;
|
||||||
const { showDatasource } = this.state;
|
const { showDatasource } = this.state;
|
||||||
@ -176,18 +191,32 @@ class DatasourceControl extends React.PureComponent {
|
|||||||
showDatasource,
|
showDatasource,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { datasource, onChange, value } = this.props;
|
const { datasource, onChange, value } = this.props;
|
||||||
|
|
||||||
|
const datasourceMenu = (
|
||||||
|
<Menu onClick={this.handleMenuItemClick}>
|
||||||
|
<Menu.Item key={CHANGE_DATASET}>{t('Change Dataset')}</Menu.Item>
|
||||||
|
<Menu.Item key={EXPLORE_IN_SQL_LAB}>
|
||||||
|
<a
|
||||||
|
href={`/superset/sqllab?datasourceKey=${value}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{t('Explore in SQL Lab')}
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
{this.props.isEditable && (
|
||||||
|
<Menu.Item key={EDIT_DATASET} data-test="edit-dataset">
|
||||||
|
{t('Edit Dataset')}
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styles className="DatasourceControl">
|
<Styles className="DatasourceControl">
|
||||||
<ControlHeader {...this.props} />
|
<ControlHeader {...this.props} />
|
||||||
<div>
|
<div>
|
||||||
<OverlayTrigger
|
<Tooltip title={t('Expand/collapse dataset configuration')}>
|
||||||
placement="top"
|
|
||||||
overlay={
|
|
||||||
<Tooltip id="toggle-dataset-tooltip">
|
|
||||||
{t('Expand/collapse dataset configuration')}
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Label
|
<Label
|
||||||
style={{ textTransform: 'none' }}
|
style={{ textTransform: 'none' }}
|
||||||
onClick={this.toggleShowDatasource}
|
onClick={this.toggleShowDatasource}
|
||||||
@ -199,43 +228,20 @@ class DatasourceControl extends React.PureComponent {
|
|||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</Label>
|
</Label>
|
||||||
</OverlayTrigger>
|
</Tooltip>
|
||||||
<TooltipWrapper
|
<Dropdown
|
||||||
label="change-datasource"
|
overlay={datasourceMenu}
|
||||||
tooltip={t('More dataset related options')}
|
trigger={['click']}
|
||||||
trigger={['hover']}
|
data-test="datasource-menu"
|
||||||
>
|
>
|
||||||
<DropdownButton
|
<Tooltip title={t('More dataset related options')}>
|
||||||
title={<Icon name="more-horiz" />}
|
<Icon
|
||||||
className=""
|
className="datasource-modal-trigger"
|
||||||
bsSize="sm"
|
data-test="datasource-menu-trigger"
|
||||||
id="datasource_menu"
|
name="more-horiz"
|
||||||
data-test="datasource-menu"
|
/>
|
||||||
>
|
</Tooltip>
|
||||||
<MenuItem eventKey="3" onClick={this.toggleChangeDatasourceModal}>
|
</Dropdown>
|
||||||
{t('Change Dataset')}
|
|
||||||
</MenuItem>
|
|
||||||
{datasource.type === 'table' && (
|
|
||||||
<MenuItem
|
|
||||||
eventKey="3"
|
|
||||||
href={`/superset/sqllab?datasourceKey=${value}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{t('Explore in SQL Lab')}
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
{this.props.isEditable && (
|
|
||||||
<MenuItem
|
|
||||||
data-test="edit-dataset"
|
|
||||||
eventKey="3"
|
|
||||||
onClick={this.toggleEditDatasourceModal}
|
|
||||||
>
|
|
||||||
{t('Edit Dataset')}
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
</DropdownButton>
|
|
||||||
</TooltipWrapper>
|
|
||||||
</div>
|
</div>
|
||||||
<Collapse in={this.state.showDatasource}>
|
<Collapse in={this.state.showDatasource}>
|
||||||
{this.renderDatasource()}
|
{this.renderDatasource()}
|
||||||
|
Loading…
Reference in New Issue
Block a user