mirror of https://github.com/apache/superset.git
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
This commit is contained in:
parent
01ddbd0697
commit
55a3404b71
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"]');
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 };
|
|
@ -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';
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue