mirror of
https://github.com/apache/superset.git
synced 2024-09-17 19:19:38 -04:00
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"]')
|
cy.get('[data-test="dashboard-builder-component-pane-tabs-navigation"]')
|
||||||
.children()
|
.within(() => {
|
||||||
.last()
|
cy.get('.ant-tabs-tab').last();
|
||||||
|
})
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
// find box plot is available from list
|
// find box plot is available from list
|
||||||
|
@ -43,6 +43,12 @@ describe('AdhocFilters', () => {
|
|||||||
cy.get('input[type=text]').focus().type('name{enter}');
|
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 => {
|
cy.get('script').then(nodes => {
|
||||||
// should load new script chunks for SQL editor
|
// should load new script chunks for SQL editor
|
||||||
expect(nodes.length).to.greaterThan(numScripts);
|
expect(nodes.length).to.greaterThan(numScripts);
|
||||||
|
@ -72,11 +72,6 @@ describe('AdhocMetrics', () => {
|
|||||||
.should('have.text', 'num')
|
.should('have.text', 'num')
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
cy.get('[data-test=option-label]')
|
|
||||||
.should('have.text', 'SUM(num)')
|
|
||||||
.first()
|
|
||||||
.click();
|
|
||||||
|
|
||||||
// add custom SQL
|
// add custom SQL
|
||||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
||||||
cy.get('[data-test=metrics-edit-popover]').within(() => {
|
cy.get('[data-test=metrics-edit-popover]').within(() => {
|
||||||
@ -103,9 +98,6 @@ describe('AdhocMetrics', () => {
|
|||||||
cy.get('[data-test=metrics]')
|
cy.get('[data-test=metrics]')
|
||||||
.find('[data-test="metric-option"]')
|
.find('[data-test="metric-option"]')
|
||||||
.should('have.length', 2);
|
.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('#metrics-edit-popover').within(() => {
|
||||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
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="datasource-menu-trigger"]').click();
|
||||||
cy.get('[data-test="edit-dataset"]').click();
|
cy.get('[data-test="edit-dataset"]').click();
|
||||||
cy.get('.ant-modal-content').within(() => {
|
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}"]`)
|
cy.get(`input[value="${newMetricName}"]`)
|
||||||
.closest('tr')
|
.closest('tr')
|
||||||
@ -140,7 +142,7 @@ describe('Time range filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cy.get('#filter-popover').within(() => {
|
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('div.PopoverSection :not(.dimmed)').within(() => {
|
||||||
cy.get('input[value="100 years ago"]');
|
cy.get('input[value="100 years ago"]');
|
||||||
cy.get('input[value="now"]');
|
cy.get('input[value="now"]');
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Tabs } from 'react-bootstrap';
|
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import configureStore from 'redux-mock-store';
|
import configureStore from 'redux-mock-store';
|
||||||
import fetchMock from 'fetch-mock';
|
import fetchMock from 'fetch-mock';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import DatasourceEditor from 'src/datasource/DatasourceEditor';
|
import DatasourceEditor from 'src/datasource/DatasourceEditor';
|
||||||
import Field from 'src/CRUD/Field';
|
import Field from 'src/CRUD/Field';
|
||||||
import mockDatasource from '../../fixtures/mockDatasource';
|
import mockDatasource from '../../fixtures/mockDatasource';
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { Tab, Tabs } from 'react-bootstrap';
|
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import AdhocFilter, {
|
import AdhocFilter, {
|
||||||
EXPRESSION_TYPES,
|
EXPRESSION_TYPES,
|
||||||
CLAUSES,
|
CLAUSES,
|
||||||
@ -82,7 +82,7 @@ describe('AdhocFilterEditPopover', () => {
|
|||||||
it('renders simple tab content by default', () => {
|
it('renders simple tab content by default', () => {
|
||||||
const { wrapper } = setup();
|
const { wrapper } = setup();
|
||||||
expect(wrapper.find(Tabs)).toExist();
|
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(Button)).toHaveLength(2);
|
||||||
expect(wrapper.find(AdhocFilterEditPopoverSimpleTabContent)).toHaveLength(
|
expect(wrapper.find(AdhocFilterEditPopoverSimpleTabContent)).toHaveLength(
|
||||||
1,
|
1,
|
||||||
@ -92,7 +92,7 @@ describe('AdhocFilterEditPopover', () => {
|
|||||||
it('renders sql tab content when the adhoc filter expressionType is sql', () => {
|
it('renders sql tab content when the adhoc filter expressionType is sql', () => {
|
||||||
const { wrapper } = setup({ adhocFilter: sqlAdhocFilter });
|
const { wrapper } = setup({ adhocFilter: sqlAdhocFilter });
|
||||||
expect(wrapper.find(Tabs)).toExist();
|
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(Button)).toHaveLength(2);
|
||||||
expect(wrapper.find(AdhocFilterEditPopoverSqlTabContent)).toExist();
|
expect(wrapper.find(AdhocFilterEditPopoverSqlTabContent)).toExist();
|
||||||
});
|
});
|
||||||
|
@ -18,11 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable no-unused-expressions */
|
/* eslint-disable no-unused-expressions */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { OverlayTrigger, Tab, Tabs, Radio } from 'react-bootstrap';
|
import { OverlayTrigger, Radio } from 'react-bootstrap';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { styledMount as mount } from 'spec/helpers/theming';
|
import { styledMount as mount } from 'spec/helpers/theming';
|
||||||
|
|
||||||
import Popover from 'src/common/components/Popover';
|
import Popover from 'src/common/components/Popover';
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import Label from 'src/components/Label';
|
import Label from 'src/components/Label';
|
||||||
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
|
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
|
||||||
import ControlHeader from 'src/explore/components/ControlHeader';
|
import ControlHeader from 'src/explore/components/ControlHeader';
|
||||||
@ -85,13 +86,13 @@ describe('DateFilterControl', () => {
|
|||||||
const popoverContentWrapper = mount(popoverContent);
|
const popoverContentWrapper = mount(popoverContent);
|
||||||
|
|
||||||
expect(popoverContentWrapper.find(Tabs)).toExist();
|
expect(popoverContentWrapper.find(Tabs)).toExist();
|
||||||
expect(popoverContentWrapper.find(Tab)).toHaveLength(2);
|
expect(popoverContentWrapper.find(Tabs.TabPane)).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders default time options', () => {
|
it('renders default time options', () => {
|
||||||
const popoverContent = wrapper.find(Popover).first().props().content;
|
const popoverContent = wrapper.find(Popover).first().props().content;
|
||||||
const popoverContentWrapper = mount(popoverContent);
|
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)).toExist();
|
||||||
expect(defaultTab.find(Radio)).toHaveLength(6);
|
expect(defaultTab.find(Radio)).toHaveLength(6);
|
||||||
@ -100,7 +101,7 @@ describe('DateFilterControl', () => {
|
|||||||
it('renders tooltips over timeframe options', () => {
|
it('renders tooltips over timeframe options', () => {
|
||||||
const popoverContent = wrapper.find(Popover).first().props().content;
|
const popoverContent = wrapper.find(Popover).first().props().content;
|
||||||
const popoverContentWrapper = mount(popoverContent);
|
const popoverContentWrapper = mount(popoverContent);
|
||||||
const defaultTab = popoverContentWrapper.find(Tab).first();
|
const defaultTab = popoverContentWrapper.find(Tabs.TabPane).first();
|
||||||
const radioTrigger = defaultTab.find(OverlayTrigger);
|
const radioTrigger = defaultTab.find(OverlayTrigger);
|
||||||
|
|
||||||
expect(radioTrigger).toExist();
|
expect(radioTrigger).toExist();
|
||||||
@ -110,7 +111,7 @@ describe('DateFilterControl', () => {
|
|||||||
it('renders the correct time range in tooltip', () => {
|
it('renders the correct time range in tooltip', () => {
|
||||||
const popoverContent = wrapper.find(Popover).first().props().content;
|
const popoverContent = wrapper.find(Popover).first().props().content;
|
||||||
const popoverContentWrapper = mount(popoverContent);
|
const popoverContentWrapper = mount(popoverContent);
|
||||||
const defaultTab = popoverContentWrapper.find(Tab).first();
|
const defaultTab = popoverContentWrapper.find(Tabs.TabPane).first();
|
||||||
const triggers = defaultTab.find(OverlayTrigger);
|
const triggers = defaultTab.find(OverlayTrigger);
|
||||||
|
|
||||||
const expectedLabels = {
|
const expectedLabels = {
|
||||||
|
@ -30,6 +30,10 @@ const notForwardedProps = ['fullWidth'];
|
|||||||
const StyledTabs = styled(AntdTabs, {
|
const StyledTabs = styled(AntdTabs, {
|
||||||
shouldForwardProp: prop => !notForwardedProps.includes(prop),
|
shouldForwardProp: prop => !notForwardedProps.includes(prop),
|
||||||
})<TabsProps>`
|
})<TabsProps>`
|
||||||
|
.ant-tabs-content-holder {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-tabs-tab {
|
.ant-tabs-tab {
|
||||||
flex: 1 1 auto;
|
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 default Tabs;
|
||||||
export { EditableTabs };
|
export { CardTabs, EditableTabs };
|
20
superset-frontend/src/common/components/Tabs/index.ts
Normal file
20
superset-frontend/src/common/components/Tabs/index.ts
Normal file
@ -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 */
|
/* eslint-env browser */
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Tabs, Tab } from 'react-bootstrap';
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import { StickyContainer, Sticky } from 'react-sticky';
|
import { StickyContainer, Sticky } from 'react-sticky';
|
||||||
import { ParentSize } from '@vx/responsive';
|
import { ParentSize } from '@vx/responsive';
|
||||||
|
|
||||||
@ -48,23 +48,24 @@ class BuilderComponentPane extends React.PureComponent {
|
|||||||
const { isSticky } = this.props;
|
const { isSticky } = this.props;
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
className="m-t-10 tabs-components"
|
|
||||||
id="tabs"
|
id="tabs"
|
||||||
|
className="tabs-components"
|
||||||
|
style={{ marginTop: '10px' }}
|
||||||
data-test="dashboard-builder-component-pane-tabs-navigation"
|
data-test="dashboard-builder-component-pane-tabs-navigation"
|
||||||
>
|
>
|
||||||
<Tab eventKey={1} title={t('Components')}>
|
<Tabs.TabPane key={1} tab={t('Components')}>
|
||||||
<NewTabs />
|
<NewTabs />
|
||||||
<NewRow />
|
<NewRow />
|
||||||
<NewColumn />
|
<NewColumn />
|
||||||
<NewHeader />
|
<NewHeader />
|
||||||
<NewMarkdown />
|
<NewMarkdown />
|
||||||
<NewDivider />
|
<NewDivider />
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
<Tab eventKey={2} title={t('Charts')} className="tab-charts">
|
<Tabs.TabPane key={2} tab={t('Charts')} className="tab-charts">
|
||||||
<SliceAdder
|
<SliceAdder
|
||||||
height={height + (isSticky ? SUPERSET_HEADER_HEIGHT : 0)}
|
height={height + (isSticky ? SUPERSET_HEADER_HEIGHT : 0)}
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 shortid from 'shortid';
|
||||||
import { styled, SupersetClient, t } from '@superset-ui/core';
|
import { styled, SupersetClient, t } from '@superset-ui/core';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import CertifiedIconWithTooltip from 'src/components/CertifiedIconWithTooltip';
|
import CertifiedIconWithTooltip from 'src/components/CertifiedIconWithTooltip';
|
||||||
import DatabaseSelector from 'src/components/DatabaseSelector';
|
import DatabaseSelector from 'src/components/DatabaseSelector';
|
||||||
@ -596,11 +597,9 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
const { datasource } = this.state;
|
const { datasource } = this.state;
|
||||||
const { spatials, all_cols: allCols } = datasource;
|
const { spatials, all_cols: allCols } = datasource;
|
||||||
return (
|
return (
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
title={
|
tab={<CollectionTabTitle collection={spatials} title={t('Spatial')} />}
|
||||||
<CollectionTabTitle collection={spatials} title={t('Spatial')} />
|
key={4}
|
||||||
}
|
|
||||||
eventKey={4}
|
|
||||||
>
|
>
|
||||||
<CollectionTable
|
<CollectionTable
|
||||||
tableColumns={['name', 'config']}
|
tableColumns={['name', 'config']}
|
||||||
@ -621,7 +620,7 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,35 +904,35 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
fullWidth={false}
|
||||||
id="table-tabs"
|
id="table-tabs"
|
||||||
data-test="edit-dataset-tabs"
|
data-test="edit-dataset-tabs"
|
||||||
onSelect={this.handleTabSelect}
|
onChange={this.handleTabSelect}
|
||||||
defaultActiveKey={activeTabKey}
|
defaultActiveKey={activeTabKey}
|
||||||
>
|
>
|
||||||
<Tab eventKey={0} title={t('Source')}>
|
<Tabs.TabPane key={0} tab={t('Source')}>
|
||||||
{activeTabKey === 0 && this.renderSourceFieldset()}
|
{this.renderSourceFieldset()}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
title={
|
tab={
|
||||||
<CollectionTabTitle
|
<CollectionTabTitle
|
||||||
collection={datasource.metrics}
|
collection={datasource.metrics}
|
||||||
title={t('Metrics')}
|
title={t('Metrics')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
eventKey={1}
|
key={1}
|
||||||
>
|
>
|
||||||
{activeTabKey === 1 && this.renderMetricCollection()}
|
{this.renderMetricCollection()}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
title={
|
tab={
|
||||||
<CollectionTabTitle
|
<CollectionTabTitle
|
||||||
collection={this.state.databaseColumns}
|
collection={this.state.databaseColumns}
|
||||||
title={t('Columns')}
|
title={t('Columns')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
eventKey={2}
|
key={2}
|
||||||
>
|
>
|
||||||
{activeTabKey === 2 && (
|
|
||||||
<div>
|
<div>
|
||||||
<ColumnCollectionTable
|
<ColumnCollectionTable
|
||||||
columns={this.state.databaseColumns}
|
columns={this.state.databaseColumns}
|
||||||
@ -950,18 +949,16 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
</Button>
|
</Button>
|
||||||
{this.state.metadataLoading && <Loading />}
|
{this.state.metadataLoading && <Loading />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Tabs.TabPane>
|
||||||
</Tab>
|
<Tabs.TabPane
|
||||||
<Tab
|
tab={
|
||||||
title={
|
|
||||||
<CollectionTabTitle
|
<CollectionTabTitle
|
||||||
collection={this.state.calculatedColumns}
|
collection={this.state.calculatedColumns}
|
||||||
title={t('Calculated Columns')}
|
title={t('Calculated Columns')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
eventKey={3}
|
key={3}
|
||||||
>
|
>
|
||||||
{activeTabKey === 3 && (
|
|
||||||
<ColumnCollectionTable
|
<ColumnCollectionTable
|
||||||
columns={this.state.calculatedColumns}
|
columns={this.state.calculatedColumns}
|
||||||
onChange={calculatedColumns =>
|
onChange={calculatedColumns =>
|
||||||
@ -979,10 +976,8 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
__expanded: true,
|
__expanded: true,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
</Tabs.TabPane>
|
||||||
</Tab>
|
<Tabs.TabPane key={4} tab={t('Settings')}>
|
||||||
<Tab eventKey={4} title={t('Settings')}>
|
|
||||||
{activeTabKey === 4 && (
|
|
||||||
<div>
|
<div>
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
<FormContainer>{this.renderSettingsFieldset()}</FormContainer>
|
<FormContainer>{this.renderSettingsFieldset()}</FormContainer>
|
||||||
@ -991,8 +986,7 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
<FormContainer>{this.renderAdvancedFieldset()}</FormContainer>
|
<FormContainer>{this.renderAdvancedFieldset()}</FormContainer>
|
||||||
</Col>
|
</Col>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Tabs.TabPane>
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</DatasourceContainer>
|
</DatasourceContainer>
|
||||||
);
|
);
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Tab, Tabs } from 'react-bootstrap';
|
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import { t } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import columnType from '../propTypes/columnType';
|
import columnType from '../propTypes/columnType';
|
||||||
import adhocMetricType from '../propTypes/adhocMetricType';
|
import adhocMetricType from '../propTypes/adhocMetricType';
|
||||||
import AdhocFilter, { EXPRESSION_TYPES } from '../AdhocFilter';
|
import AdhocFilter, { EXPRESSION_TYPES } from '../AdhocFilter';
|
||||||
@ -46,7 +46,7 @@ const propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const startingWidth = 300;
|
const startingWidth = 300;
|
||||||
const startingHeight = 190;
|
const startingHeight = 240;
|
||||||
|
|
||||||
export default class AdhocFilterEditPopover extends React.Component {
|
export default class AdhocFilterEditPopover extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -144,10 +144,10 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
data-test="adhoc-filter-edit-tabs"
|
data-test="adhoc-filter-edit-tabs"
|
||||||
style={{ height: this.state.height, width: this.state.width }}
|
style={{ height: this.state.height, width: this.state.width }}
|
||||||
>
|
>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
className="adhoc-filter-edit-tab"
|
className="adhoc-filter-edit-tab"
|
||||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
key={EXPRESSION_TYPES.SIMPLE}
|
||||||
title="Simple"
|
tab="Simple"
|
||||||
>
|
>
|
||||||
<AdhocFilterEditPopoverSimpleTabContent
|
<AdhocFilterEditPopoverSimpleTabContent
|
||||||
adhocFilter={this.state.adhocFilter}
|
adhocFilter={this.state.adhocFilter}
|
||||||
@ -157,11 +157,11 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
onHeightChange={this.adjustHeight}
|
onHeightChange={this.adjustHeight}
|
||||||
partitionColumn={partitionColumn}
|
partitionColumn={partitionColumn}
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
className="adhoc-filter-edit-tab"
|
className="adhoc-filter-edit-tab"
|
||||||
eventKey={EXPRESSION_TYPES.SQL}
|
key={EXPRESSION_TYPES.SQL}
|
||||||
title="Custom SQL"
|
tab="Custom SQL"
|
||||||
>
|
>
|
||||||
{!this.props.datasource ||
|
{!this.props.datasource ||
|
||||||
this.props.datasource.type !== 'druid' ? (
|
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
|
Custom SQL Filters are not available on druid datasources
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div>
|
<div>
|
||||||
<Button buttonSize="small" onClick={this.props.onClose} cta>
|
<Button buttonSize="small" onClick={this.props.onClose} cta>
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 Button from 'src/components/Button';
|
||||||
import Select from 'src/components/Select';
|
import Select from 'src/components/Select';
|
||||||
import { t } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
@ -50,7 +51,7 @@ const defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const startingWidth = 300;
|
const startingWidth = 300;
|
||||||
const startingHeight = 180;
|
const startingHeight = 240;
|
||||||
|
|
||||||
export default class AdhocMetricEditPopover extends React.Component {
|
export default class AdhocMetricEditPopover extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -222,13 +223,12 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
defaultActiveKey={adhocMetric.expressionType}
|
defaultActiveKey={adhocMetric.expressionType}
|
||||||
className="adhoc-metric-edit-tabs"
|
className="adhoc-metric-edit-tabs"
|
||||||
style={{ height: this.state.height, width: this.state.width }}
|
style={{ height: this.state.height, width: this.state.width }}
|
||||||
onSelect={this.refreshAceEditor}
|
onChange={this.refreshAceEditor}
|
||||||
animation={false}
|
|
||||||
>
|
>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
className="adhoc-metric-edit-tab"
|
className="adhoc-metric-edit-tab"
|
||||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
key={EXPRESSION_TYPES.SIMPLE}
|
||||||
title="Simple"
|
tab="Simple"
|
||||||
>
|
>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
@ -251,11 +251,11 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
<Tab
|
<Tabs.TabPane
|
||||||
className="adhoc-metric-edit-tab"
|
className="adhoc-metric-edit-tab"
|
||||||
eventKey={EXPRESSION_TYPES.SQL}
|
key={EXPRESSION_TYPES.SQL}
|
||||||
title="Custom SQL"
|
tab="Custom SQL"
|
||||||
data-test="adhoc-metric-edit-tab#custom"
|
data-test="adhoc-metric-edit-tab#custom"
|
||||||
>
|
>
|
||||||
{this.props.datasourceType !== 'druid' ? (
|
{this.props.datasourceType !== 'druid' ? (
|
||||||
@ -282,7 +282,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
Custom SQL Metrics are not available on druid datasources
|
Custom SQL Metrics are not available on druid datasources
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
|
@ -21,9 +21,11 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-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 { t, styled } from '@superset-ui/core';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import ControlPanelSection from './ControlPanelSection';
|
import ControlPanelSection from './ControlPanelSection';
|
||||||
import ControlRow from './ControlRow';
|
import ControlRow from './ControlRow';
|
||||||
import Control from './Control';
|
import Control from './Control';
|
||||||
@ -44,7 +46,7 @@ const Styles = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
.remove-alert {
|
.remove-alert {
|
||||||
cursor: 'pointer';
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#controlSections {
|
#controlSections {
|
||||||
display: flex;
|
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 {
|
class ControlPanelsContainer extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -193,6 +204,7 @@ class ControlPanelsContainer extends React.Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showCustomizeTab = displaySectionsToRender.length > 0;
|
||||||
return (
|
return (
|
||||||
<Styles>
|
<Styles>
|
||||||
{this.props.alert && (
|
{this.props.alert && (
|
||||||
@ -208,16 +220,20 @@ class ControlPanelsContainer extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
<Tabs id="controlSections" data-test="control-tabs">
|
<ControlPanelsTabs
|
||||||
<Tab eventKey="query" title={t('Data')}>
|
id="controlSections"
|
||||||
|
data-test="control-tabs"
|
||||||
|
fullWidth={showCustomizeTab}
|
||||||
|
>
|
||||||
|
<Tabs.TabPane key="query" tab={t('Data')}>
|
||||||
{querySectionsToRender.map(this.renderControlPanelSection)}
|
{querySectionsToRender.map(this.renderControlPanelSection)}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
{displaySectionsToRender.length > 0 && (
|
{showCustomizeTab && (
|
||||||
<Tab eventKey="display" title={t('Customize')}>
|
<Tabs.TabPane key="display" tab={t('Customize')}>
|
||||||
{displaySectionsToRender.map(this.renderControlPanelSection)}
|
{displaySectionsToRender.map(this.renderControlPanelSection)}
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
)}
|
)}
|
||||||
</Tabs>
|
</ControlPanelsTabs>
|
||||||
</Styles>
|
</Styles>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,6 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
OverlayTrigger,
|
OverlayTrigger,
|
||||||
Radio,
|
Radio,
|
||||||
Tab,
|
|
||||||
Tabs,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'react-bootstrap';
|
} from 'react-bootstrap';
|
||||||
import Popover from 'src/common/components/Popover';
|
import Popover from 'src/common/components/Popover';
|
||||||
@ -37,6 +35,7 @@ import 'react-datetime/css/react-datetime.css';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { t, styled, withTheme } from '@superset-ui/core';
|
import { t, styled, withTheme } from '@superset-ui/core';
|
||||||
|
|
||||||
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import {
|
import {
|
||||||
buildTimeRangeString,
|
buildTimeRangeString,
|
||||||
formatTimeRange,
|
formatTimeRange,
|
||||||
@ -435,15 +434,17 @@ class DateFilterControl extends React.Component {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultActiveKey={this.state.tab === TABS.DEFAULTS ? 1 : 2}
|
defaultActiveKey={this.state.tab === TABS.DEFAULTS ? '1' : '2'}
|
||||||
id="type"
|
id="type"
|
||||||
className="time-filter-tabs"
|
className="time-filter-tabs"
|
||||||
onSelect={this.changeTab}
|
onSelect={this.changeTab}
|
||||||
>
|
>
|
||||||
<Tab eventKey={1} title="Defaults">
|
<Tabs.TabPane key="1" tab="Defaults" forceRender>
|
||||||
|
<div style={{ marginLeft: '8px' }}>
|
||||||
<FormGroup>{timeFrames}</FormGroup>
|
<FormGroup>{timeFrames}</FormGroup>
|
||||||
</Tab>
|
</div>
|
||||||
<Tab eventKey={2} title="Custom">
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane key="2" tab="Custom">
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<PopoverSection
|
<PopoverSection
|
||||||
title="Relative to today"
|
title="Relative to today"
|
||||||
@ -573,7 +574,7 @@ class DateFilterControl extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</PopoverSection>
|
</PopoverSection>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Tab>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div className="clearfix">
|
<div className="clearfix">
|
||||||
<Button
|
<Button
|
||||||
|
Loading…
Reference in New Issue
Block a user