mirror of
https://github.com/apache/superset.git
synced 2026-04-21 17:14:57 +00:00
refactor: Replace react-bootstrap tabs with Antd tabs (#11090)
* Replace tabs in profile * Replace tabs in SouthPane * Replace tabs in TabbedSqlEditors * Add typing for dropdown * Add license * Remove isSelected * Fixes * Add data-test * Fix test * Remove unnecessary style * Remove unnecessary style * Tests fix * Tests fix * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Tabs.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/common/components/Dropdown.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Remove inModal prop * Remove inModal from storybook * Move inline style to styled component Co-authored-by: Evan Rusackas <evan@preset.io>
This commit is contained in:
committed by
GitHub
parent
53cd05d74a
commit
4fd993c4e0
@@ -19,7 +19,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import shortid from 'shortid';
|
||||
import { Alert, Tab, Tabs } from 'react-bootstrap';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
import Tabs from 'src/common/components/Tabs';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { t } from '@superset-ui/core';
|
||||
@@ -140,9 +141,8 @@ export class SouthPane extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
const dataPreviewTabs = props.dataPreviewQueries.map(query => (
|
||||
<Tab
|
||||
title={t('Preview: `%s`', decodeURIComponent(query.tableName))}
|
||||
eventKey={query.id}
|
||||
<Tabs.TabPane
|
||||
tab={t('Preview: `%s`', decodeURIComponent(query.tableName))}
|
||||
key={query.id}
|
||||
>
|
||||
<ResultSet
|
||||
@@ -154,29 +154,27 @@ export class SouthPane extends React.PureComponent {
|
||||
height={innerTabContentHeight}
|
||||
displayLimit={this.props.displayLimit}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs.TabPane>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="SouthPane" ref={this.southPaneRef}>
|
||||
<Tabs
|
||||
bsStyle="tabs"
|
||||
animation={false}
|
||||
defaultActiveKey={this.props.activeSouthPaneTab}
|
||||
className="SouthPaneTabs"
|
||||
id={shortid.generate()}
|
||||
activeKey={this.props.activeSouthPaneTab}
|
||||
onSelect={this.switchTab}
|
||||
fullWidth={false}
|
||||
>
|
||||
<Tab title={t('Results')} eventKey="Results">
|
||||
<Tabs.TabPane tab={t('Results')} key="Results">
|
||||
{results}
|
||||
</Tab>
|
||||
<Tab title={t('Query History')} eventKey="History">
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab={t('Query History')} key="History">
|
||||
<QueryHistory
|
||||
queries={props.editorQueries}
|
||||
actions={props.actions}
|
||||
displayLimit={props.displayLimit}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs.TabPane>
|
||||
{dataPreviewTabs}
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -18,18 +18,19 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MenuItem, DropdownButton, Tab, Tabs } from 'react-bootstrap';
|
||||
import { EditableTabs } from 'src/common/components/Tabs';
|
||||
import { Dropdown } from 'src/common/components/Dropdown';
|
||||
import { Menu } from 'src/common/components';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import URI from 'urijs';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { styled, t } from '@superset-ui/core';
|
||||
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
|
||||
import { areArraysShallowEqual } from 'src/reduxUtils';
|
||||
import * as Actions from '../actions/sqlLab';
|
||||
import SqlEditor from './SqlEditor';
|
||||
import { areArraysShallowEqual } from '../../reduxUtils';
|
||||
import TabStatusIcon from './TabStatusIcon';
|
||||
import Icon from '../../components/Icon';
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
@@ -57,6 +58,10 @@ const defaultProps = {
|
||||
|
||||
let queryCount = 1;
|
||||
|
||||
const TabTitle = styled.span`
|
||||
margin-right: ${({ theme }) => theme.gridUnit * 2}px;
|
||||
`;
|
||||
|
||||
class TabbedSqlEditors extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -74,6 +79,8 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
this,
|
||||
);
|
||||
this.duplicateQueryEditor = this.duplicateQueryEditor.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleEdit = this.handleEdit.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -253,17 +260,23 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleSelect(key) {
|
||||
if (key === 'add_tab') {
|
||||
const qeid = this.props.tabHistory[this.props.tabHistory.length - 1];
|
||||
if (key !== qeid) {
|
||||
const queryEditor = this.props.queryEditors.find(qe => qe.id === key);
|
||||
this.props.actions.switchQueryEditor(
|
||||
queryEditor,
|
||||
this.props.displayLimit,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
handleEdit(key, action) {
|
||||
if (action === 'remove') {
|
||||
const qe = this.props.queryEditors.find(qe => qe.id === key);
|
||||
this.removeQueryEditor(qe);
|
||||
}
|
||||
if (action === 'add') {
|
||||
this.newQueryEditor();
|
||||
} else {
|
||||
const qeid = this.props.tabHistory[this.props.tabHistory.length - 1];
|
||||
if (key !== qeid) {
|
||||
const queryEditor = this.props.queryEditors.find(qe => qe.id === key);
|
||||
this.props.actions.switchQueryEditor(
|
||||
queryEditor,
|
||||
this.props.displayLimit,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,10 +299,7 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const editors = this.props.queryEditors.map((qe, i) => {
|
||||
const isSelected =
|
||||
this.activeQueryEditor() && this.activeQueryEditor().id === qe.id;
|
||||
|
||||
const editors = this.props.queryEditors.map(qe => {
|
||||
let latestQuery;
|
||||
if (qe.latestQueryId) {
|
||||
latestQuery = this.props.queries[qe.latestQueryId];
|
||||
@@ -300,123 +310,97 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
}
|
||||
const state = latestQuery ? latestQuery.state : '';
|
||||
|
||||
const title = (
|
||||
<>
|
||||
{qe.title} <TabStatusIcon tabState={state} />{' '}
|
||||
<Icon
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
cursor="pointer"
|
||||
name="cancel-x"
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
className="close-btn"
|
||||
key="1"
|
||||
onClick={() => this.removeQueryEditor(qe)}
|
||||
/>
|
||||
</>
|
||||
data-test="close-tab-menu-option"
|
||||
>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-close" />
|
||||
</div>
|
||||
{t('Close tab')}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" onClick={() => this.renameTab(qe)}>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-i-cursor" />
|
||||
</div>
|
||||
{t('Rename tab')}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" onClick={this.toggleLeftBar}>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-cogs" />
|
||||
</div>
|
||||
{this.state.hideLeftBar ? t('Expand tool bar') : t('Hide tool bar')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="4"
|
||||
onClick={() => this.removeAllOtherQueryEditors(qe)}
|
||||
>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-times-circle-o" />
|
||||
</div>
|
||||
{t('Close all other tabs')}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="5" onClick={() => this.duplicateQueryEditor(qe)}>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-files-o" />
|
||||
</div>
|
||||
{t('Duplicate tab')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
const tabTitle = (
|
||||
|
||||
const tabHeader = (
|
||||
<>
|
||||
{isSelected && (
|
||||
<DropdownButton
|
||||
data-test="dropdown-toggle-button"
|
||||
bsSize="small"
|
||||
id={`ddbtn-tab-${i}`}
|
||||
title={' '}
|
||||
noCaret
|
||||
>
|
||||
<MenuItem
|
||||
className="close-btn"
|
||||
eventKey="1"
|
||||
onClick={() => this.removeQueryEditor(qe)}
|
||||
data-test="close-tab-menu-option"
|
||||
>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-close" />
|
||||
</div>
|
||||
{t('Close tab')}
|
||||
</MenuItem>
|
||||
<MenuItem eventKey="2" onClick={() => this.renameTab(qe)}>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-i-cursor" />
|
||||
</div>
|
||||
{t('Rename tab')}
|
||||
</MenuItem>
|
||||
<MenuItem eventKey="3" onClick={this.toggleLeftBar}>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-cogs" />
|
||||
</div>
|
||||
{this.state.hideLeftBar
|
||||
? t('Expand tool bar')
|
||||
: t('Hide tool bar')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
eventKey="4"
|
||||
onClick={() => this.removeAllOtherQueryEditors(qe)}
|
||||
>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-times-circle-o" />
|
||||
</div>
|
||||
{t('Close all other tabs')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
eventKey="5"
|
||||
onClick={() => this.duplicateQueryEditor(qe)}
|
||||
>
|
||||
<div className="icon-container">
|
||||
<i className="fa fa-files-o" />
|
||||
</div>
|
||||
{t('Duplicate tab')}
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
)}
|
||||
<span className="ddbtn-tab">{title}</span>
|
||||
<div data-test="dropdown-toggle-button">
|
||||
<Dropdown overlay={menu} trigger={['click']} />
|
||||
</div>
|
||||
<TabTitle>{qe.title}</TabTitle> <TabStatusIcon tabState={state} />{' '}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<Tab key={qe.id} title={tabTitle} eventKey={qe.id}>
|
||||
{isSelected && (
|
||||
<SqlEditor
|
||||
tables={this.props.tables.filter(
|
||||
xt => xt.queryEditorId === qe.id,
|
||||
)}
|
||||
queryEditor={qe}
|
||||
editorQueries={this.state.queriesArray}
|
||||
dataPreviewQueries={this.state.dataPreviewQueries}
|
||||
latestQuery={latestQuery}
|
||||
database={database}
|
||||
actions={this.props.actions}
|
||||
hideLeftBar={this.state.hideLeftBar}
|
||||
defaultQueryLimit={this.props.defaultQueryLimit}
|
||||
maxRow={this.props.maxRow}
|
||||
displayLimit={this.props.displayLimit}
|
||||
saveQueryWarning={this.props.saveQueryWarning}
|
||||
scheduleQueryWarning={this.props.scheduleQueryWarning}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<EditableTabs.TabPane
|
||||
key={qe.id}
|
||||
tab={tabHeader}
|
||||
// for tests - key prop isn't handled by enzyme well bcs it's a react keyword
|
||||
data-key={qe.id}
|
||||
>
|
||||
<SqlEditor
|
||||
tables={this.props.tables.filter(xt => xt.queryEditorId === qe.id)}
|
||||
queryEditor={qe}
|
||||
editorQueries={this.state.queriesArray}
|
||||
dataPreviewQueries={this.state.dataPreviewQueries}
|
||||
latestQuery={latestQuery}
|
||||
database={database}
|
||||
actions={this.props.actions}
|
||||
hideLeftBar={this.state.hideLeftBar}
|
||||
defaultQueryLimit={this.props.defaultQueryLimit}
|
||||
maxRow={this.props.maxRow}
|
||||
displayLimit={this.props.displayLimit}
|
||||
saveQueryWarning={this.props.saveQueryWarning}
|
||||
scheduleQueryWarning={this.props.scheduleQueryWarning}
|
||||
/>
|
||||
</EditableTabs.TabPane>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
bsStyle="tabs"
|
||||
animation={false}
|
||||
<EditableTabs
|
||||
activeKey={this.props.tabHistory[this.props.tabHistory.length - 1]}
|
||||
onSelect={this.handleSelect.bind(this)}
|
||||
id="a11y-query-editor-tabs"
|
||||
className="SqlEditorTabs"
|
||||
data-test="sql-editor-tabs"
|
||||
onChange={this.handleSelect}
|
||||
fullWidth={false}
|
||||
hideAdd={this.props.offline}
|
||||
onEdit={this.handleEdit}
|
||||
addIcon={<i data-test="add-tab-icon" className="fa fa-plus-circle" />}
|
||||
>
|
||||
{editors}
|
||||
<Tab
|
||||
title={
|
||||
<div>
|
||||
<i data-test="add-tab-icon" className="fa fa-plus-circle" />
|
||||
|
||||
</div>
|
||||
}
|
||||
className="addEditorTab"
|
||||
eventKey="add_tab"
|
||||
disabled={this.props.offline}
|
||||
/>
|
||||
</Tabs>
|
||||
</EditableTabs>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user