You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2020/10/31 05:06:04 UTC
[incubator-superset] branch master updated: refactor: Replace
react-bootstrap tabs with Antd tabs (#11118)
This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 55a3404 refactor: Replace react-bootstrap tabs with Antd tabs (#11118)
55a3404 is described below
commit 55a3404b71232a1cfd6d978f666945cde37c99e2
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Sat Oct 31 06:05:31 2020 +0100
refactor: Replace react-bootstrap tabs with Antd tabs (#11118)
* Replace tabs in BuilderComponentPane
* Replace tabs in ControlPanelsContainer
* Replace tabs in AdhocMetricEditPopover
* Replace Tabs in DatasourceEditor
* Replace tabs in AdhocFilterEditPopover
* Replace tabs in DateFilterControl
* Bug fix
* Change Tab styles
* Fix tests
* Fix cypress tests
* Lint fix
* Fix tests
* Change Tabs style in ControlPanelsContainer
* Change tabs content height
* Lint fix
* Add data test
* Fix e2e test
* Move Tabs file to separate dir
* Fix after rebase
* Fix e2e tests
* Fix after rebase
---
.../integration/dashboard/edit_mode.test.js | 5 +-
.../integration/explore/AdhocFilters.test.ts | 6 +
.../integration/explore/AdhocMetrics.test.ts | 8 --
.../cypress/integration/explore/control.test.ts | 6 +-
.../datasource/DatasourceEditor_spec.jsx | 2 +-
.../components/AdhocFilterEditPopover_spec.jsx | 6 +-
.../explore/components/DateFilterControl_spec.jsx | 11 +-
.../src/common/components/{ => Tabs}/Tabs.tsx | 16 ++-
.../src/common/components/Tabs/index.ts | 20 +++
.../dashboard/components/BuilderComponentPane.jsx | 13 +-
.../src/datasource/DatasourceEditor.jsx | 140 ++++++++++-----------
.../explore/components/AdhocFilterEditPopover.jsx | 20 +--
.../explore/components/AdhocMetricEditPopover.jsx | 24 ++--
.../explore/components/ControlPanelsContainer.jsx | 34 +++--
.../components/controls/DateFilterControl.jsx | 17 +--
15 files changed, 188 insertions(+), 140 deletions(-)
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
index c628837..4832c44 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
@@ -47,8 +47,9 @@ describe('Dashboard edit mode', () => {
});
cy.get('[data-test="dashboard-builder-component-pane-tabs-navigation"]')
- .children()
- .last()
+ .within(() => {
+ cy.get('.ant-tabs-tab').last();
+ })
.click();
// find box plot is available from list
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
index 9b7c5ae..d9057d3 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
@@ -43,6 +43,12 @@ describe('AdhocFilters', () => {
cy.get('input[type=text]').focus().type('name{enter}');
});
+ // antd tabs do lazy loading, so we need to click on tab with ace editor
+ cy.get('#filter-edit-popover').within(() => {
+ cy.get('.ant-tabs-tab').contains('Custom SQL').click();
+ cy.get('.ant-tabs-tab').contains('Simple').click();
+ });
+
cy.get('script').then(nodes => {
// should load new script chunks for SQL editor
expect(nodes.length).to.greaterThan(numScripts);
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
index e839fc2..7c085c3 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
@@ -72,11 +72,6 @@ describe('AdhocMetrics', () => {
.should('have.text', 'num')
.click();
- cy.get('[data-test=option-label]')
- .should('have.text', 'SUM(num)')
- .first()
- .click();
-
// add custom SQL
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
cy.get('[data-test=metrics-edit-popover]').within(() => {
@@ -103,9 +98,6 @@ describe('AdhocMetrics', () => {
cy.get('[data-test=metrics]')
.find('[data-test="metric-option"]')
.should('have.length', 2);
- cy.get('[data-test=metrics]').within(() => {
- cy.contains('[data-test="metric-option"]', 'SUM(sum_girls)').click();
- });
cy.get('#metrics-edit-popover').within(() => {
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
index 4cf22df..e4bc157f 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
@@ -70,7 +70,9 @@ describe('Datasource control', () => {
cy.get('[data-test="datasource-menu-trigger"]').click();
cy.get('[data-test="edit-dataset"]').click();
cy.get('.ant-modal-content').within(() => {
- cy.get('a[role="tab"]').contains('Metrics').click();
+ cy.get('[data-test="collection-tab-Metrics"]')
+ .contains('Metrics')
+ .click();
});
cy.get(`input[value="${newMetricName}"]`)
.closest('tr')
@@ -140,7 +142,7 @@ describe('Time range filter', () => {
});
cy.get('#filter-popover').within(() => {
- cy.get('div.tab-pane.active').within(() => {
+ cy.get('div.ant-tabs-tabpane-active').within(() => {
cy.get('div.PopoverSection :not(.dimmed)').within(() => {
cy.get('input[value="100 years ago"]');
cy.get('input[value="now"]');
diff --git a/superset-frontend/spec/javascripts/datasource/DatasourceEditor_spec.jsx b/superset-frontend/spec/javascripts/datasource/DatasourceEditor_spec.jsx
index ce0d3ea..7fb2b2a 100644
--- a/superset-frontend/spec/javascripts/datasource/DatasourceEditor_spec.jsx
+++ b/superset-frontend/spec/javascripts/datasource/DatasourceEditor_spec.jsx
@@ -17,12 +17,12 @@
* under the License.
*/
import React from 'react';
-import { Tabs } from 'react-bootstrap';
import { shallow } from 'enzyme';
import configureStore from 'redux-mock-store';
import fetchMock from 'fetch-mock';
import thunk from 'redux-thunk';
+import Tabs from 'src/common/components/Tabs';
import DatasourceEditor from 'src/datasource/DatasourceEditor';
import Field from 'src/CRUD/Field';
import mockDatasource from '../../fixtures/mockDatasource';
diff --git a/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx b/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
index c8e91c6..c28ac9a 100644
--- a/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
@@ -20,9 +20,9 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import { Tab, Tabs } from 'react-bootstrap';
import Button from 'src/components/Button';
+import Tabs from 'src/common/components/Tabs';
import AdhocFilter, {
EXPRESSION_TYPES,
CLAUSES,
@@ -82,7 +82,7 @@ describe('AdhocFilterEditPopover', () => {
it('renders simple tab content by default', () => {
const { wrapper } = setup();
expect(wrapper.find(Tabs)).toExist();
- expect(wrapper.find(Tab)).toHaveLength(2);
+ expect(wrapper.find(Tabs.TabPane)).toHaveLength(2);
expect(wrapper.find(Button)).toHaveLength(2);
expect(wrapper.find(AdhocFilterEditPopoverSimpleTabContent)).toHaveLength(
1,
@@ -92,7 +92,7 @@ describe('AdhocFilterEditPopover', () => {
it('renders sql tab content when the adhoc filter expressionType is sql', () => {
const { wrapper } = setup({ adhocFilter: sqlAdhocFilter });
expect(wrapper.find(Tabs)).toExist();
- expect(wrapper.find(Tab)).toHaveLength(2);
+ expect(wrapper.find(Tabs.TabPane)).toHaveLength(2);
expect(wrapper.find(Button)).toHaveLength(2);
expect(wrapper.find(AdhocFilterEditPopoverSqlTabContent)).toExist();
});
diff --git a/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx b/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
index fd1984d..49ac950 100644
--- a/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
@@ -18,11 +18,12 @@
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
-import { OverlayTrigger, Tab, Tabs, Radio } from 'react-bootstrap';
+import { OverlayTrigger, Radio } from 'react-bootstrap';
import sinon from 'sinon';
import { styledMount as mount } from 'spec/helpers/theming';
import Popover from 'src/common/components/Popover';
+import Tabs from 'src/common/components/Tabs';
import Label from 'src/components/Label';
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
import ControlHeader from 'src/explore/components/ControlHeader';
@@ -85,13 +86,13 @@ describe('DateFilterControl', () => {
const popoverContentWrapper = mount(popoverContent);
expect(popoverContentWrapper.find(Tabs)).toExist();
- expect(popoverContentWrapper.find(Tab)).toHaveLength(2);
+ expect(popoverContentWrapper.find(Tabs.TabPane)).toHaveLength(2);
});
it('renders default time options', () => {
const popoverContent = wrapper.find(Popover).first().props().content;
const popoverContentWrapper = mount(popoverContent);
- const defaultTab = popoverContentWrapper.find(Tab).first();
+ const defaultTab = popoverContentWrapper.find(Tabs.TabPane).first();
expect(defaultTab.find(Radio)).toExist();
expect(defaultTab.find(Radio)).toHaveLength(6);
@@ -100,7 +101,7 @@ describe('DateFilterControl', () => {
it('renders tooltips over timeframe options', () => {
const popoverContent = wrapper.find(Popover).first().props().content;
const popoverContentWrapper = mount(popoverContent);
- const defaultTab = popoverContentWrapper.find(Tab).first();
+ const defaultTab = popoverContentWrapper.find(Tabs.TabPane).first();
const radioTrigger = defaultTab.find(OverlayTrigger);
expect(radioTrigger).toExist();
@@ -110,7 +111,7 @@ describe('DateFilterControl', () => {
it('renders the correct time range in tooltip', () => {
const popoverContent = wrapper.find(Popover).first().props().content;
const popoverContentWrapper = mount(popoverContent);
- const defaultTab = popoverContentWrapper.find(Tab).first();
+ const defaultTab = popoverContentWrapper.find(Tabs.TabPane).first();
const triggers = defaultTab.find(OverlayTrigger);
const expectedLabels = {
diff --git a/superset-frontend/src/common/components/Tabs.tsx b/superset-frontend/src/common/components/Tabs/Tabs.tsx
similarity index 91%
rename from superset-frontend/src/common/components/Tabs.tsx
rename to superset-frontend/src/common/components/Tabs/Tabs.tsx
index 7627354..027f286 100644
--- a/superset-frontend/src/common/components/Tabs.tsx
+++ b/superset-frontend/src/common/components/Tabs/Tabs.tsx
@@ -30,6 +30,10 @@ const notForwardedProps = ['fullWidth'];
const StyledTabs = styled(AntdTabs, {
shouldForwardProp: prop => !notForwardedProps.includes(prop),
})<TabsProps>`
+ .ant-tabs-content-holder {
+ overflow: auto;
+ }
+
.ant-tabs-tab {
flex: 1 1 auto;
@@ -120,5 +124,15 @@ EditableTabs.TabPane.defaultProps = {
),
};
+const StyledCardTabs = styled(EditableTabs)``;
+
+const CardTabs = Object.assign(StyledCardTabs, {
+ TabPane: StyledTabPane,
+});
+
+CardTabs.defaultProps = {
+ type: 'card',
+};
+
export default Tabs;
-export { EditableTabs };
+export { CardTabs, EditableTabs };
diff --git a/superset-frontend/src/common/components/Tabs/index.ts b/superset-frontend/src/common/components/Tabs/index.ts
new file mode 100644
index 0000000..32bc0c3
--- /dev/null
+++ b/superset-frontend/src/common/components/Tabs/index.ts
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+export * from './Tabs';
+export { default } from './Tabs';
diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
index df18290..a693f87 100644
--- a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
+++ b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
@@ -19,7 +19,7 @@
/* eslint-env browser */
import PropTypes from 'prop-types';
import React from 'react';
-import { Tabs, Tab } from 'react-bootstrap';
+import Tabs from 'src/common/components/Tabs';
import { StickyContainer, Sticky } from 'react-sticky';
import { ParentSize } from '@vx/responsive';
@@ -48,23 +48,24 @@ class BuilderComponentPane extends React.PureComponent {
const { isSticky } = this.props;
return (
<Tabs
- className="m-t-10 tabs-components"
id="tabs"
+ className="tabs-components"
+ style={{ marginTop: '10px' }}
data-test="dashboard-builder-component-pane-tabs-navigation"
>
- <Tab eventKey={1} title={t('Components')}>
+ <Tabs.TabPane key={1} tab={t('Components')}>
<NewTabs />
<NewRow />
<NewColumn />
<NewHeader />
<NewMarkdown />
<NewDivider />
- </Tab>
- <Tab eventKey={2} title={t('Charts')} className="tab-charts">
+ </Tabs.TabPane>
+ <Tabs.TabPane key={2} tab={t('Charts')} className="tab-charts">
<SliceAdder
height={height + (isSticky ? SUPERSET_HEADER_HEIGHT : 0)}
/>
- </Tab>
+ </Tabs.TabPane>
</Tabs>
);
}
diff --git a/superset-frontend/src/datasource/DatasourceEditor.jsx b/superset-frontend/src/datasource/DatasourceEditor.jsx
index 30fb17a..5530662 100644
--- a/superset-frontend/src/datasource/DatasourceEditor.jsx
+++ b/superset-frontend/src/datasource/DatasourceEditor.jsx
@@ -18,10 +18,11 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Alert, Badge, Col, Radio, Tabs, Tab, Well } from 'react-bootstrap';
+import { Alert, Badge, Col, Radio, Well } from 'react-bootstrap';
import shortid from 'shortid';
import { styled, SupersetClient, t } from '@superset-ui/core';
+import Tabs from 'src/common/components/Tabs';
import Button from 'src/components/Button';
import CertifiedIconWithTooltip from 'src/components/CertifiedIconWithTooltip';
import DatabaseSelector from 'src/components/DatabaseSelector';
@@ -596,11 +597,9 @@ class DatasourceEditor extends React.PureComponent {
const { datasource } = this.state;
const { spatials, all_cols: allCols } = datasource;
return (
- <Tab
- title={
- <CollectionTabTitle collection={spatials} title={t('Spatial')} />
- }
- eventKey={4}
+ <Tabs.TabPane
+ tab={<CollectionTabTitle collection={spatials} title={t('Spatial')} />}
+ key={4}
>
<CollectionTable
tableColumns={['name', 'config']}
@@ -621,7 +620,7 @@ class DatasourceEditor extends React.PureComponent {
),
}}
/>
- </Tab>
+ </Tabs.TabPane>
);
}
@@ -905,94 +904,89 @@ class DatasourceEditor extends React.PureComponent {
</Alert>
</div>
<Tabs
+ fullWidth={false}
id="table-tabs"
data-test="edit-dataset-tabs"
- onSelect={this.handleTabSelect}
+ onChange={this.handleTabSelect}
defaultActiveKey={activeTabKey}
>
- <Tab eventKey={0} title={t('Source')}>
- {activeTabKey === 0 && this.renderSourceFieldset()}
- </Tab>
- <Tab
- title={
+ <Tabs.TabPane key={0} tab={t('Source')}>
+ {this.renderSourceFieldset()}
+ </Tabs.TabPane>
+ <Tabs.TabPane
+ tab={
<CollectionTabTitle
collection={datasource.metrics}
title={t('Metrics')}
/>
}
- eventKey={1}
+ key={1}
>
- {activeTabKey === 1 && this.renderMetricCollection()}
- </Tab>
- <Tab
- title={
+ {this.renderMetricCollection()}
+ </Tabs.TabPane>
+ <Tabs.TabPane
+ tab={
<CollectionTabTitle
collection={this.state.databaseColumns}
title={t('Columns')}
/>
}
- eventKey={2}
+ key={2}
>
- {activeTabKey === 2 && (
- <div>
- <ColumnCollectionTable
- columns={this.state.databaseColumns}
- onChange={databaseColumns =>
- this.setColumns({ databaseColumns })
- }
- />
- <Button
- buttonStyle="primary"
- onClick={this.syncMetadata}
- className="sync-from-source"
- >
- {t('Sync columns from source')}
- </Button>
- {this.state.metadataLoading && <Loading />}
- </div>
- )}
- </Tab>
- <Tab
- title={
+ <div>
+ <ColumnCollectionTable
+ columns={this.state.databaseColumns}
+ onChange={databaseColumns =>
+ this.setColumns({ databaseColumns })
+ }
+ />
+ <Button
+ buttonStyle="primary"
+ onClick={this.syncMetadata}
+ className="sync-from-source"
+ >
+ {t('Sync columns from source')}
+ </Button>
+ {this.state.metadataLoading && <Loading />}
+ </div>
+ </Tabs.TabPane>
+ <Tabs.TabPane
+ tab={
<CollectionTabTitle
collection={this.state.calculatedColumns}
title={t('Calculated Columns')}
/>
}
- eventKey={3}
+ key={3}
>
- {activeTabKey === 3 && (
- <ColumnCollectionTable
- columns={this.state.calculatedColumns}
- onChange={calculatedColumns =>
- this.setColumns({ calculatedColumns })
- }
- editableColumnName
- showExpression
- allowAddItem
- allowEditDataType
- itemGenerator={() => ({
- column_name: '<new column>',
- filterable: true,
- groupby: true,
- expression: '<enter SQL expression here>',
- __expanded: true,
- })}
- />
- )}
- </Tab>
- <Tab eventKey={4} title={t('Settings')}>
- {activeTabKey === 4 && (
- <div>
- <Col md={6}>
- <FormContainer>{this.renderSettingsFieldset()}</FormContainer>
- </Col>
- <Col md={6}>
- <FormContainer>{this.renderAdvancedFieldset()}</FormContainer>
- </Col>
- </div>
- )}
- </Tab>
+ <ColumnCollectionTable
+ columns={this.state.calculatedColumns}
+ onChange={calculatedColumns =>
+ this.setColumns({ calculatedColumns })
+ }
+ editableColumnName
+ showExpression
+ allowAddItem
+ allowEditDataType
+ itemGenerator={() => ({
+ column_name: '<new column>',
+ filterable: true,
+ groupby: true,
+ expression: '<enter SQL expression here>',
+ __expanded: true,
+ })}
+ />
+ </Tabs.TabPane>
+ <Tabs.TabPane key={4} tab={t('Settings')}>
+ <div>
+ <Col md={6}>
+ <FormContainer>{this.renderSettingsFieldset()}</FormContainer>
+ </Col>
+ <Col md={6}>
+ <FormContainer>{this.renderAdvancedFieldset()}</FormContainer>
+ </Col>
+ </div>
+ </Tabs.TabPane>
</Tabs>
</DatasourceContainer>
);
diff --git a/superset-frontend/src/explore/components/AdhocFilterEditPopover.jsx b/superset-frontend/src/explore/components/AdhocFilterEditPopover.jsx
index 34f885c..11b5b69 100644
--- a/superset-frontend/src/explore/components/AdhocFilterEditPopover.jsx
+++ b/superset-frontend/src/explore/components/AdhocFilterEditPopover.jsx
@@ -18,10 +18,10 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Tab, Tabs } from 'react-bootstrap';
import Button from 'src/components/Button';
import { t } from '@superset-ui/core';
+import Tabs from 'src/common/components/Tabs';
import columnType from '../propTypes/columnType';
import adhocMetricType from '../propTypes/adhocMetricType';
import AdhocFilter, { EXPRESSION_TYPES } from '../AdhocFilter';
@@ -46,7 +46,7 @@ const propTypes = {
};
const startingWidth = 300;
-const startingHeight = 190;
+const startingHeight = 240;
export default class AdhocFilterEditPopover extends React.Component {
constructor(props) {
@@ -144,10 +144,10 @@ export default class AdhocFilterEditPopover extends React.Component {
data-test="adhoc-filter-edit-tabs"
style={{ height: this.state.height, width: this.state.width }}
>
- <Tab
+ <Tabs.TabPane
className="adhoc-filter-edit-tab"
- eventKey={EXPRESSION_TYPES.SIMPLE}
- title="Simple"
+ key={EXPRESSION_TYPES.SIMPLE}
+ tab="Simple"
>
<AdhocFilterEditPopoverSimpleTabContent
adhocFilter={this.state.adhocFilter}
@@ -157,11 +157,11 @@ export default class AdhocFilterEditPopover extends React.Component {
onHeightChange={this.adjustHeight}
partitionColumn={partitionColumn}
/>
- </Tab>
- <Tab
+ </Tabs.TabPane>
+ <Tabs.TabPane
className="adhoc-filter-edit-tab"
- eventKey={EXPRESSION_TYPES.SQL}
- title="Custom SQL"
+ key={EXPRESSION_TYPES.SQL}
+ tab="Custom SQL"
>
{!this.props.datasource ||
this.props.datasource.type !== 'druid' ? (
@@ -176,7 +176,7 @@ export default class AdhocFilterEditPopover extends React.Component {
Custom SQL Filters are not available on druid datasources
</div>
)}
- </Tab>
+ </Tabs.TabPane>
</Tabs>
<div>
<Button buttonSize="small" onClick={this.props.onClose} cta>
diff --git a/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx b/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx
index 4ee85a3..d53d9df 100644
--- a/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx
+++ b/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx
@@ -18,7 +18,8 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { FormGroup, Tab, Tabs } from 'react-bootstrap';
+import { FormGroup } from 'react-bootstrap';
+import Tabs from 'src/common/components/Tabs';
import Button from 'src/components/Button';
import Select from 'src/components/Select';
import { t } from '@superset-ui/core';
@@ -50,7 +51,7 @@ const defaultProps = {
};
const startingWidth = 300;
-const startingHeight = 180;
+const startingHeight = 240;
export default class AdhocMetricEditPopover extends React.Component {
constructor(props) {
@@ -222,13 +223,12 @@ export default class AdhocMetricEditPopover extends React.Component {
defaultActiveKey={adhocMetric.expressionType}
className="adhoc-metric-edit-tabs"
style={{ height: this.state.height, width: this.state.width }}
- onSelect={this.refreshAceEditor}
- animation={false}
+ onChange={this.refreshAceEditor}
>
- <Tab
+ <Tabs.TabPane
className="adhoc-metric-edit-tab"
- eventKey={EXPRESSION_TYPES.SIMPLE}
- title="Simple"
+ key={EXPRESSION_TYPES.SIMPLE}
+ tab="Simple"
>
<FormGroup>
<FormLabel>
@@ -251,11 +251,11 @@ export default class AdhocMetricEditPopover extends React.Component {
autoFocus
/>
</FormGroup>
- </Tab>
- <Tab
+ </Tabs.TabPane>
+ <Tabs.TabPane
className="adhoc-metric-edit-tab"
- eventKey={EXPRESSION_TYPES.SQL}
- title="Custom SQL"
+ key={EXPRESSION_TYPES.SQL}
+ tab="Custom SQL"
data-test="adhoc-metric-edit-tab#custom"
>
{this.props.datasourceType !== 'druid' ? (
@@ -282,7 +282,7 @@ export default class AdhocMetricEditPopover extends React.Component {
Custom SQL Metrics are not available on druid datasources
</div>
)}
- </Tab>
+ </Tabs.TabPane>
</Tabs>
<div>
<Button
diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx
index e834c6d..eeb3ce4 100644
--- a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx
+++ b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx
@@ -21,9 +21,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
-import { Alert, Tab, Tabs } from 'react-bootstrap';
+import { Alert } from 'react-bootstrap';
+import { css } from '@emotion/core';
import { t, styled } from '@superset-ui/core';
+import Tabs from 'src/common/components/Tabs';
import ControlPanelSection from './ControlPanelSection';
import ControlRow from './ControlRow';
import Control from './Control';
@@ -44,7 +46,7 @@ const Styles = styled.div`
height: 100%;
max-height: 100%;
.remove-alert {
- cursor: 'pointer';
+ cursor: pointer;
}
#controlSections {
display: flex;
@@ -61,6 +63,15 @@ const Styles = styled.div`
}
`;
+const ControlPanelsTabs = styled(Tabs)`
+ ${({ fullWidth }) =>
+ css`
+ .ant-tabs-nav-list {
+ width: ${fullWidth ? '100%' : '50%'};
+ }
+ `}
+`;
+
class ControlPanelsContainer extends React.Component {
constructor(props) {
super(props);
@@ -193,6 +204,7 @@ class ControlPanelsContainer extends React.Component {
}
});
+ const showCustomizeTab = displaySectionsToRender.length > 0;
return (
<Styles>
{this.props.alert && (
@@ -208,16 +220,20 @@ class ControlPanelsContainer extends React.Component {
/>
</Alert>
)}
- <Tabs id="controlSections" data-test="control-tabs">
- <Tab eventKey="query" title={t('Data')}>
+ <ControlPanelsTabs
+ id="controlSections"
+ data-test="control-tabs"
+ fullWidth={showCustomizeTab}
+ >
+ <Tabs.TabPane key="query" tab={t('Data')}>
{querySectionsToRender.map(this.renderControlPanelSection)}
- </Tab>
- {displaySectionsToRender.length > 0 && (
- <Tab eventKey="display" title={t('Customize')}>
+ </Tabs.TabPane>
+ {showCustomizeTab && (
+ <Tabs.TabPane key="display" tab={t('Customize')}>
{displaySectionsToRender.map(this.renderControlPanelSection)}
- </Tab>
+ </Tabs.TabPane>
)}
- </Tabs>
+ </ControlPanelsTabs>
</Styles>
);
}
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
index f7d498c..81053d0 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
@@ -26,8 +26,6 @@ import {
MenuItem,
OverlayTrigger,
Radio,
- Tab,
- Tabs,
Tooltip,
} from 'react-bootstrap';
import Popover from 'src/common/components/Popover';
@@ -37,6 +35,7 @@ import 'react-datetime/css/react-datetime.css';
import moment from 'moment';
import { t, styled, withTheme } from '@superset-ui/core';
+import Tabs from 'src/common/components/Tabs';
import {
buildTimeRangeString,
formatTimeRange,
@@ -435,15 +434,17 @@ class DateFilterControl extends React.Component {
}}
>
<Tabs
- defaultActiveKey={this.state.tab === TABS.DEFAULTS ? 1 : 2}
+ defaultActiveKey={this.state.tab === TABS.DEFAULTS ? '1' : '2'}
id="type"
className="time-filter-tabs"
onSelect={this.changeTab}
>
- <Tab eventKey={1} title="Defaults">
- <FormGroup>{timeFrames}</FormGroup>
- </Tab>
- <Tab eventKey={2} title="Custom">
+ <Tabs.TabPane key="1" tab="Defaults" forceRender>
+ <div style={{ marginLeft: '8px' }}>
+ <FormGroup>{timeFrames}</FormGroup>
+ </div>
+ </Tabs.TabPane>
+ <Tabs.TabPane key="2" tab="Custom">
<FormGroup>
<PopoverSection
title="Relative to today"
@@ -573,7 +574,7 @@ class DateFilterControl extends React.Component {
</div>
</PopoverSection>
</FormGroup>
- </Tab>
+ </Tabs.TabPane>
</Tabs>
<div className="clearfix">
<Button